设计模式 - 强制执行子类的某些行为

时间:2014-12-18 14:05:00

标签: java inheritance design-patterns

有一个设计模式问题(一些与Java相关的术语,这是我当前的项目)。

代码的当前布局:

class Game - holds game state and manages logic,

Super abstract class Player 

玩家拥有不同类型玩家的子类(AI,人类等)。

每位玩家最多可以进行三次移动(A,B,C),但必须按顺序进行。因此,玩家可以轮流选择以下任何移动顺序:         (A,B),         (公元前),         (A,B,C)         (A,C),         (一个),         等等

玩家应该在每次移动之间收到反馈,以便他们决定是执行另一次移动还是结束。 假设类型为抽象播放器,这里有两种设计:

解决方案1: 对于设置通话player.takeTurn(game)中的所有玩家。所以每个玩家都知道轮到他们的时候,他们会引用当前的Game对象。当takeTurn()返回时,他们的回合结束。 Player.takeTurn被播放器的所有子类覆盖。在该方法中,任何希望执行移动的玩家都可以引用传入的Game对象。例如:

    game.makeMoveA(),
    game.makeMoveB(),
    etc

Game.makeMove()可以返回ok / error值来告诉玩家该移动是否合法。此外,更新的游戏状态可由Game对象使用,该对象仍在takeTurn()方法的范围内。 问题是你依赖于所有的子类来记住调用makeMove()如果他们不这样做或者如果他们以错误的顺序调用它们怎么办?我想错误顺序的调用方法可以由异常/错误消息处理,但是我们仍然存在这样的问题,即没有任何东西强制实例化的类实际响应并进行移动。

解决方案2: 抽象类Player包含三个抽象方法getMoveA getMoveB和getMoveC。 因此,所有继承者都必须实现这些方法。 抽象超类Player包含一个方法takeTurn()。

    takeTurn(Game game) {
      game.makeMove(this.getMoveA())
      game.makeMove(this.getMoveB());
      etc
    }

这很好,因为行为被强制执行,但现在我们有一个混乱的问题,即如何向进行移动的玩家提供反馈。如果这是非法移动等等,你可以强制执行另一个方法handleMoveResponse()但是每个玩家必须跟踪成功/错误消息所指的移动。

有什么想法吗?很想听听你对此的看法。

非常感谢

1 个答案:

答案 0 :(得分:0)

在我看来,你试图让你的要求符合模式,而不是在看到模式之前分解要求。

实现您的要求的简短尝试产生了这一点。那里有一个Strategy模式和一个Template模式,似乎没有你提到的问题。

enum Move {

    A, B, C;
}

class Strategy {

    final List<Move> moves;

    public Strategy(List<Move> moves) {
        // TODO: Make sure it is valid.
        this.moves = moves;
    }
}

class Game {

}

abstract class Player {

    // Call before each move.
    abstract Strategy getStrategy(Game game);

    void move(Game game, Move move) {
        // By default do nothing.
    }
}

/**
 * The rules control the game.
 */
class Rules {

    public void play(Game game, Player player) {
        while (!gameOver(game)) {
            Strategy strategy = player.getStrategy(game);
            for (Move move : strategy.moves) {
                player.move(game, move);
                // Do your feedback here.
            }
        }
    }

    private boolean gameOver(Game game) {
        return false;
    }
}