Skip to the content.

State(状态模式)

什么是状态模式呢?

有时候做一件事会存在很多的状态,而在不同的状态之下会有不同的行为。而状态模式就是根据不同的状态来改变不同的行为

下面看一下状态模式的UML类图

State(状态模式)的UML类图

如果你看过之前的策略模式的话,你会发现这两个模式的类图其实是一模一样的

但即使在UML类图上这两个模式一样,这两个模式的目的和本质都是不一样的

概念较抽象,还是上代码吧~

状态模式的简单实现

在日常生活中,做每一件事都有一系列的状态,就拿打游戏来举例吧

现在有一个玩家,他打算玩一款打怪升级的游戏,那么在玩游戏的过程中,他会有一系列的状态:打怪时的状态,升级时的状态等等

现在先抽象一个游戏状态的类,它具有以下行为:

那么根据玩游戏的状态划分,可以粗略的划分为:

那么不同的状态,它的行为肯定是不一样的,如果在以往的代码编写中,肯定会使用if-else或者switch-case来解决这种简单的问题

但是随着产品的迭代,这样程序的扩展性和鲁棒性都将变差,所以对于这种不同情况有不同行为实现的情况下,选择状态模式是一种不错选择

首先,需要先将状态抽象出来形成一个接口

public interface GameState {
    /*打怪*/
    public void killMonster();
    /*获得经验*/
    public void gainExperience();
    /*进入下一关*/
    public void next();
    /*捡拾物品*/
    public void pick();
}

那么接下来就可以根据不同的状态开始展开不同的行为实现了:

游戏开始状态

public class GameStartState implements GameState {
    /*击杀一只怪物*/
    @Override
    public void killMonster() {
        System.out.println("Kill a Monster");
    }

    /*获得5经验值*/
    @Override
    public void gainExperience() {
        System.out.println("Gain 5 EXP");
    }

    /*进入下一关*/
    @Override
    public void next() {
        System.out.println("Good! please enter next level");
    }

    /*捡到一件好东西*/
    @Override
    public void pick() {
        System.out.println("Wow! You pick a good thing");
    }
}

游戏结束状态

public class GameOverState implements GameState {
    /*游戏没开始,无法打怪*/
    @Override
    public void killMonster() {
        System.out.println("Please start game first");
    }
    /*游戏没开始,无法获得经验*/
    @Override
    public void gainExperience() {

    }
    /*游戏已经结束,下一步就是选择是否重新开始*/
    @Override
    public void next() {
        System.out.println("You want to challenge again?");
    }
    /*游戏没开始,无好东西可以捡*/
    @Override
    public void pick() {
        System.out.println("Please start game first");
    }
}

什么状态下该干什么都已经想好了,下一步就是来一个玩家开始游戏了

public class Player {
    /*游戏状态*/
    GameState state;
    /*游戏状态的设置*/
    public void setState(GameState state) {
        this.state = state;
    }
    /*游戏开始*/
    public void gameStart() {
        setState(new GameStartState());
        System.out.println("\n-----Game Start, ready to fight-----\n");
    }
    /*游戏结束*/
    public void gameOver(){
        setState(new GameOverState());
        System.out.println("\n-----         Game Over        -----\n");
    }
    /*打怪*/
    public void killMonster(){
        state.killMonster();
    }
    /*获得经验*/
    public void gainExperience() {
        state.gainExperience();
    }
    /*下一关*/
    public void next(){
        state.next();
    }
    /*捡东西*/
    public void pick(){
        state.pick();
    }

    public static void main(String[] args) {
        /*游戏开始后的一系列操作和结束后的操作*/
        Player player = new Player();
        player.gameStart();
        player.killMonster();
        player.gainExperience();
        player.next();
        player.pick();
        player.gameOver();
        player.next();
        player.killMonster();
        player.pick();
    }
}

代码内都有注释,思路还是比较清晰的,可以看到,玩家代码中没有对游戏状态的逻辑判断,使得代码看起来更加的简洁

看看玩家玩的怎么样吧~


-----Game Start, ready to fight-----

Kill a Monster
Gain 5 EXP
Good! please enter next level
Wow! You pick a good thing

-----         Game Over        -----

You want to challenge again?
Please start game first
Please start game first

根据输出结果对比可以看到,在游戏开始和结束后,玩家执行相同的操作都会有不同的实现结果

总结

来总结一下状态模式的优缺点吧

END.