状态模式

作者: 某昆 | 来源:发表于2018-09-15 11:29 被阅读5次

    本文主要内容

    • 状态模式简介
    • 状态模式实例
    • 总结

    1、状态模式简介

    当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类

    状态模式的一般使用场景:

    • 一个对象的行为取决于它的状态,并且必须在运行时根据它的状态改变它的行为
    • 代码中包含大量与状态有关的条件语句,如有很多if else

    从第2条来看,状态模式与策略模式类似,但它和策略模式是不一样的,状态模式的所有状态,肯定是有切换的,不同状态不同的行为,遇到不同的环境状态会变化。它的内含偏向于,不同状态下不同的处理逻辑。而策略模式,偏向于同样的功能不同的实现。

    状态模式UML图

    2、状态模式实例

    我们以电视遥控器为例。遥控器可以调台,并且调节音量。但电视只有在开机的状态下才能实现上述功能,关机的时候按钮无效。那么我们应该怎么去抽象这个状态类呢?

    使用状态模式时,非常重要的一点是分清楚哪里是不同状态下能做的操作?哪些是切换状态的因素。遥控器这个例子中,开关机显示是切换状态的因素,调台和调音量显示是不同状态下的操作。

    当我们在定义状态接口时,一定不能把导致状态切换的因素也写到状态接口中,否则会很别扭。这么一分析,状态接口可以这么写:

    public interface TvState {
    
    public void nextChannel();
    public void preChannel();
    public void turnUp();
    public void turnDown();
    }
    

    开机状态实现:

    public class PowerOnState implements TvState{
    
    @Override
    public void nextChannel() {
        System.out.println("下一个频道");
    }
    
    @Override
    public void preChannel() {
        System.out.println("上一个频道");
    }
    
    @Override
    public void turnUp() {
        System.out.println("增大音量");
    }
    
    @Override
    public void turnDown() {
        System.out.println("减小音量");
    }
    
    }
    

    关机状态什么都不能做,所以这些函数都是空函数:

    public class PowerOffState implements TvState{
    
    @Override
    public void nextChannel() {
    }
    
    @Override
    public void preChannel() {
    }
    
    @Override
    public void turnUp() {
    }
    
    @Override
    public void turnDown() {
    }
    }
    

    定义一个开关机的接口:

    public interface PowerController {
    
    public void powerOn();
    public void powerOff();
    }
    

    遥控器:

    public class TvController implements PowerController{
    
    TvState mState;
    
    public void setState(TvState tvState){
        mState = tvState;
    }
    
    @Override
    public void powerOn() {
        System.out.println("开机了");
        setState(new PowerOnState());
    }
    
    @Override
    public void powerOff() {
        System.out.println("关机了");
        setState(new PowerOffState());
    }
    
    public void nextChannel() {
        mState.nextChannel();
    }
    
    public void preChannel() {
        mState.preChannel();
    }
    
    public void turnUp() {
        mState.turnUp();
    }
    
    public void turnDown() {
        mState.turnDown();
    }
    
    public static void main(String[] args) {
        TvController controller = new TvController();
        controller.powerOn();
        controller.nextChannel();
        controller.turnDown();
        controller.powerOff();
        controller.turnUp();
    }
    }
    

    3、总结

    示例比较简单,最重要是理解状态模式。尤其是状态模式接口的定义,为啥不把开关机这个方法也写到状态接口当中来呢?因为如果开关机也在状态接口中,那怎么来切换状态呢?导致状态切换的原因一定要放在外面。另外就是认真体会下状态模式和策略模式之间的差异了。策略模式侧面的是不同算法,而状态模式侧重的是不同状态。

    相关文章

      网友评论

        本文标题:状态模式

        本文链接:https://www.haomeiwen.com/subject/eymzgftx.html