6月更文挑战|设计模式 —— 状态模式

489 阅读3分钟

这是我参与更文挑战的第8天,活动详情查看:更文挑战

状态模式

状态模式行为由状态决定,不同状态下有不同行为。看似状态模式结构和策略模式相似,但在目的和概念上两者还是有所不同的。状态模式的行为是平行且不可替换,策略模式是彼此独立,可互相替换。简单来说状态模式下的对象是处于内部结构,每个状态对象都有共同的抽象基类,在该模式下状态在内部改变,其执行行为也在内部发生变化。策略模式对于对象来说是外放的,控制器从外部接收希望的策略方案,然后去执行相应的功能。在概念上来讲两者模式还是有所差异,状态侧重在状态发生变化所执行方法不再属于同一过程和结果,策略侧重在策略方案上在执行同一方法过程输出不同结果。

普通方式

平常开发中在一些业务场景下会有多个状态的情况。当遇到这种情况时,通常做法是设置状态标记位,然后定义状态静态变量代表每一种状态。比如powerState代表这电脑的运作状态。可以设置电脑的运作状态,在不同状态下执行电脑不同方法时会通过if-else去判断状态是否符合预期可执行相应程序。

以下代码逻辑过于耦合,职责不单一,完全不符合设计原则。在之后状态结构发生改变时会牵涉到整个类的改变,这就不是希望看到的结果。

public class ComputerController{
    private final POWER_ON = 1;
    private final POWER_OFF = 2;
    
    private int powerState = 1;
    
    public void open(){
        powerState = POWER_ON;
    }
    
    public void close(){
        powerState = POWER_OFF;
        
    }
    
    public void playGame(){
        if(powerState == POWER_ON){
            runGame();
        }
    }
    
    public void playMusic(){
        if(powerState == POWER_ON){
            runMusic();
        }
    }  
    public void awaitOpen(){
        if(powerState == POWER_OFF){
            timeOpen();
        }
    }       
    
}

状态模式方式

设置一个PowerState抽象接口类,实现所有状态下的所有方法;Controller作为控制器抽象类可设置不同状态;PowerOpenState实现PowerState抽象类方法,然后实现对应状态下的能力,其中awaitOpen不属于该状态下的能力就是一个空方法;PowerCloseState则只需要实现本状态下的awaitOpen;ComputerController实现Controller抽象类,可配置不同状态对象,同时实现状态下每个方法。在这个时候配置不同状态执行不同方法时不存在多余的if-else判断,逻辑也变清晰易懂。

public interface PowerState{
    void playGame();
    void playMusic();
    void awaitOpen();
}

public interface Controller{
    void open();
    void close();
}

public PowerOpenState extends PowerState{
    @override 
    void playGame(){
        runGame();
    }
    @override 
    void playMusic(){
        runMusic();
    }
    @override 
    void awaitOpen(){

    }
}

public PowerCloseState extends PowerState{
    @override 
    void playGame(){}
    @override 
    void playMusic(){}
    @override 
    void awaitOpen(){
        timeOpen();
    }
}

public class ComputerController extends Controller{
    PowerState powerState;
    
    @override 
    void open(){
       powerState = new PowerOpenState();
    }
    @override 
    void close(){
       powerState = new PowerCloseState();
    }
    

    void playGame(){
        powerState.playGame();
    }
 
    void playMusic(){
        powerState.playGame();
    }

    void awaitOpen(){
        powerState.awaitOpen();
    }    
    
}

总结

状态模式优点在于对于同一行为在不同状态下的表现,将if-else行为以多态的形式实现。在if-else形式下实现上对于逻辑耦合度太高,后期维护繁琐且容易出错,但并不代表if-else就是不好的形式,具体问题具体分析,需要思考在什么场景下状态模式是更优解才是使用该设计模式的意义所在。

当然状态模式也有它的缺点,会产生无用方法,增加系统类和对象个数。