我是Akka的新手,我很喜欢这项技术,但我无法理解如何在没有业务逻辑的情况下为演员做饭。假设我需要制作一款游戏。游戏对玩家有限制,在选择赢家后不能多选。Akka。如何摆脱演员内部的业务逻辑?
public class Game {
private List<String> participants;
private int maxParticipants;
private String winner;
private boolean ended;
public int getMaxParticipants() {
return maxParticipants;
}
public int getParticipantsSize() {
return participants.size();
}
public void addParticipant(String participant) {
participants.add(participant);
}
public boolean isEnded() {
return ended;
}
public void chooseWinner() {
if (ended) {
// do some stuff
}
winner = participants.get(randomNumber);
ended = true;
}
}
和演员类:
public class GameActor extends UntypedActor {
private Game game = new Game();
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof AddParticipant) {
// For example there can't be more then two participants.
// I want to have this "if" inside my Game class, not here
if (game.getParticipantsSize() >= game.getMaxParticipants()) {
// do something about it
}
game.addParticipant(message.getParticipant());
}else if (message instanceof ChooseWinner){
// We can't choose winner after game ended. I don't want to have this logic here
game.chooseWinner();
}
}
}
现在我明白了几种方法。在简单的情况下,他们都可以工作,但他们都非常有限:
上升例外。仅适用于负面情况。如果一切正常,我 不知道下一步该怎么做。另外catch块是丑陋的,我不想 想维护GameFullException,GameEndedException等等。
返回一些价值。像addParticipant中的布尔值,如果它是 成功。要么是有限的使用情况,要么是 返回值的另一层ifelse。
- 游戏类可以引发事件,我的演员可以订阅它。
像这样:
public class Game {
private List<Listener> listeners = new ArrayList<>();
public void addListener(Listener listener) {
listeners.add(listener);
}
public void riseEvent(Event event) {
listeners.forEach(l->l.handle(event));
}
}
而且单个收听的是演员:
public class GameActor extends UntypedActor {
private Game game = new Game();
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof AddParticipant) {
game.addParticipant(message.getParticipant());
}else if (message instanceof ChooseWinner){
game.chooseWinner();
}else if(message instanceof Event){
// do something with actor state if needed
}
}
public void handle(Event event) {
self().tell(event, self());
}
}
第三人似乎最有趣和最强大的我,但它只是似乎错了,我的模型这里有一个用户,它是一个演员,然后由模型事件发送给自己。 当然,这个游戏课只是一个例子(我不确定它是否是我的问题的一个很好的例证),这样简单的逻辑可以在演员中完成,并且没问题,但我对如何解耦的原理感兴趣演员的业务逻辑,因为我不认为演员是许多原因的商业逻辑的好地方。我对Scala和Java都很感兴趣。一些例子会很棒。
也许你是对的,我只需要做一点小小的转变。起初我想到演员喜欢另一种同步技术。主要原因是因为我不想在演员中拥有业务逻辑,因为演员很难测试简单的函数和类。但也许这是我需要为简单并发付出的代价。 –
我明白你为什么会这样说,但我认为你是对的。演员很容易测试。发送消息给他们,并测试他们的反应!并发性问题不是你可以避免的 - 如果你想要一个类同时接收消息,扩展Actor类型可能是允许它们参与的最简单的机制。 –