我是一个Akka的新手,对这项技术感到兴奋,但是我不明白如何在没有业务逻辑的情况下编写Actor。假设我需要制作一款游戏。游戏有玩家数量限制,并且在选择赢家后不能再次选择。
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。
- Game类可以触发事件,我的actor可以订阅它。
就像这样:
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都很感兴趣。如果能提供一些示例就更好了。