状态设计模式在网球卡塔中的使用

State Design Pattern Usage In Tennis Kata

我正在解决著名的Tennis Kata Problem

我有一个关于状态设计模式的基本问题。 程序需要输出网球比赛的比分。

下面enum表示一个选手在网球比赛中的不同得分:

public enum Score{
Love,
Fifteen,
Thirty,
Fourty,
Deuce,
Advantage,
Game
}

我打算在这里使用的典型 classes 是: TennisGame(主要class处理逻辑),Player(会维护自己的Score),ScoreCalculator(有基于Rules的Score操作逻辑) 当发生表明哪个用户得分的外部事件发生时,分数将发生变化。

这里的问题是 - 应该如何处理跟踪分数变化的逻辑?

非常幼稚的做法是:

if(score == Love){
  score = Fifteen; //move score to Fifteen 
}else if(score == Fifteen){
  score = Thirty; //move score to Thirty
}

但是这样会导致很多if else条件。 我正在考虑为此使用状态模式。

但这里的问题是,这里的上下文(例如:TennisGame class)将封装 State,不会根据 State 的变化做任何事情。

玩家得分后返回分数

任何人都可以在这里建议使用状态模式的正确设计应该是什么吗?

首先,我认为您的分数枚举中不需要 Deuce,因为它是分数为 40-40 时的状态。在这种情况下,当您遇到得分为 30-40 的情况时,如果玩家一得分,则您必须更改两个玩家的状态。这将很难管理。从我的角度来看,这是更好用的枚举:

public enum Score {
    Love, Fifteen, Thirty, Forty, Advantage, Game
}

第二个我觉得比较好的是不保存当前玩家得分,而是保存双方玩家的胜球数,然后根据这些数计算得分。使用以下代码很容易实现:

public Score calculateScore(int playerWinBalls, int opponentWinBalls) {
    if (playerWinBalls <= 3) {
        return Score.values()[playerWinBalls];
    }
    int winBallsDifference = playerWinBalls - opponentWinBalls;
    if (winBallsDifference <= 0) {
        return Score.Forty;
    }
    if (winBallsDifference == 1) {
        return Score.Advantage;
    }
    return Score.Game;
}

现在剩下的是 API 来增加给定球员的赢球率,它可能是像 winBall(String playerName) 这样的方法,有单独的方法,如 winBallP1()/winBallP2() 或也许是别的。