【问题标题】:Design pattern - enforcing certain behaviour of subclasses设计模式 - 强制子类的某些行为
【发布时间】:2014-12-18 14:04:59
【问题描述】:

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

当前代码布局:

class Game - holds game state and manages logic,

Super abstract class Player 

玩家有不同类型玩家(人工智能、人类等)的子类。

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

玩家应该在每个动作之间收到反馈,以便他们可以决定是执行另一个动作还是结束他们的回合。 假设这里的抽象 Player 类型集是我有两种设计:

解决方案 1: 对于集合中的所有玩家,请致电player.takeTurn(game)。所以每个玩家都知道什么时候轮到他们,并且他们拥有对当前 Game 对象的引用。当 takeTurn() 返回时,他们的回合结束。 Player.takeTurn 被 player 的所有子类覆盖。在该方法中,任何希望执行移动的玩家都可以引用传入的 Game 对象。示例:

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

Game.makeMove() 可以返回 ok/error 值来告诉玩家移动是否合法。此外,更新后的游戏状态可通过仍在 takeTurn() 方法范围内的 Game 对象获得。 问题是您依赖所有子类记住调用 makeMove() 如果它们不调用或者调用顺序错误怎么办?我猜想以错误的顺序调用方法可能会被异常/错误消息处理,但我们仍然有一个问题,即没有任何东西强制实例化的类实际响应并采取行动。

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

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

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

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

非常感谢

【问题讨论】:

  • @Jayan 所以这正是我在第二个解决方案中提出的,但我已经说明了一些问题,如果这是可能的,需要解决这些问题。
  • 您正在编写这些Player 类吗?如果他们的行为不正确,那是一个错误吗?或者您是否接受可能故意行为不端的第三方实施?你想保护自己免受什么伤害?根据答案,将采用截然不同的解决方案。

标签: java inheritance design-patterns


【解决方案1】:

在我看来,您是在尝试让您的需求适应模式,而不是在看到模式之前分解需求。

实现您的要求的简短尝试产生了这一点。那里有一个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;
    }
}

【讨论】:

  • 看起来很有趣。对不起,我可以澄清一下, Player.move 方法只是为了让玩家可以得到响应吗?另外,请记住,玩家应该有机会根据之前的反馈是否执行下一步。所以举个例子,玩家可能会选择移动 A,(例如掷骰子),得到一个不好的结果并选择不做 B。
  • @SaadAttieh 也许你可以在你的策略中提供一个删除方法。
猜你喜欢
  • 2015-10-24
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 2014-09-16
相关资源
最近更新 更多