• 设计模式(二十)状态模式


    1、定义

      当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。主要解决的是当控制一个对象转换的条件表达式过于复杂时的状态,即把状态的判断逻辑转移到表示不同状态的一系列类当中。

    2、UML类图

                                                               

      其中,Context类与环境角色,用于维护一个ConcreteState子类的实例,这个实例定义当前的状态;State为抽象状态角色,定义一个接口以封装与Context的一个特定接口状态相关的行为;ConcreteState是具体状态角色,每个子类实现一个与Context的一个状态相关的行为。

    (1)Context类

      环境角色具有两个职责,即处理本状态必须完成的任务,即处理本状态必须完成的任务,及决定是否可以过渡到其他状态。对于环境角色,有几个不成文的约束:

    • 即把状态对象声明为静态常量,有几个状态对象就声明几个状态常量;
    • 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。
     1 /**
     2  * @author it-小林
     3  * @desc   环境角色
     4  * @date 2021年09月26日 18:20
     5  */
     6 public class Context {
     7 
     8     //定义状态
     9     public final static State STATE1 = new ConcreteState1();
    10     public final static State STATE2 = new ConcreteState2();
    11 
    12     //当前状态
    13     private State currentState;
    14 
    15     //获得当前状态
    16     public State getCurrentState() {
    17         return currentState;
    18     }
    19 
    20     public void setCurrentState(State currentState) {
    21         this.currentState = currentState;
    22         this.currentState.setContext(this);
    23     }
    24 
    25     public void handle1() {
    26         this.currentState.handle1();
    27     }
    28 
    29     public void handle2() {
    30         this.currentState.handle2();
    31     }
    32 }

    (2)State抽象状态类

      抽象环境中声明一个环境角色,提供各个状态类自行访问,并且提供所有状态的抽象行为,由各个实现类实现。

     1 /**
     2  * @author it-小林
     3  * @desc state抽象状态类
     4  * @date 2021年09月26日 18:20
     5  */
     6 public abstract class State {
     7 
     8     protected Context context;
     9 
    10     public void setContext(Context context){
    11         this.context = context;
    12     }
    13 
    14     /**
    15      * 行为1
    16      */
    17     public abstract void handle1();
    18 
    19     /**
    20      * 行为2
    21      */
    22     public abstract void handle2();
    23 }

    (3)具体状态

      具体状态实现,这里以定义ConcreteState1和ConcreteState2两个具体状态类为例。

     1 /**
     2  * @author it-小林
     3  * @desc  具体类1
     4  * @date 2021年09月26日 18:28
     5  */
     6 public class ConcreteState1 extends State{
     7     @Override
     8     public void handle1() {
     9         System.out.println("ConcreteState1 的 handle1 方法");
    10     }
    11 
    12     @Override
    13     public void handle2() {
    14         System.out.println("ConcreteState1 的 handle2 方法");
    15     }
    16 }
     1 /**
     2  * @author it-小林
     3  * @desc   具体类2
     4  * @date 2021年09月26日 18:29
     5  */
     6 public class ConcreteState2 extends State{
     7     @Override
     8     public void handle1() {
     9         System.out.println("ConcreteState2 的 handle1 方法");
    10     }
    11 
    12     @Override
    13     public void handle2() {
    14         System.out.println("ConcreteState2 的 handle2 方法");
    15     }
    16 }

    (4)Client客户端

      定义Context环境角色,初始化具体状态1,执行行为观察结果。

     1 /**
     2  * @author it-小林
     3  * @desc   客户端
     4  * @date 2021年09月26日 18:30
     5  */
     6 public class Client {
     7     public static void main(String[] args) {
     8         //定义环境角色
     9         Context context = new Context();
    10         //初始化状态
    11         context.setCurrentState(new ConcreteState1());
    12         //行为执行
    13         context.handle1();
    14         context.handle2();
    15 
    16         //初始化状态
    17         context.setCurrentState(new ConcreteState2());
    18         //行为执行
    19         context.handle1();
    20         context.handle2();
    21     }
    22 }

    运行结果:

                                             

    3、优缺点

    优点:

    • 结构清晰,避免了过多的switch case  或if else语句的使用;
    • 很好地体现了开闭原则和单一职责原则,想要增加状态就增加子类,想要修改状态就修改子类即可;
    • 封装性非常好,状态变化放置到了类的内部来实现,外部调用不需要知道类内部如何实现状态和行为的变换。

    缺点:

    • 子类太多,也即类膨胀。

    4、使用场景

    • 行为随状态改变而改变的场景;
    • 条件、分支判断语句的替代者。

    5、实例

    • 电梯,有运行状态、开门状态、闭门状态、停止状态等;
    • 运动员可以有正常状态、非正常状态和超长状态。

    7、注意事项

    • 在行为受状态约束的情况下可以使用状态模式,使用时对象的状态最好不要超过5个。

         

    如本文有侵权行为,请及时与本人联系,多多包涵! 小生初出茅庐,多多指教!

    本文来自博客园,作者:it-小林,转载请注明原文链接:https://www.cnblogs.com/linruitao/p/15067873.html

  • 相关阅读:
    hitachi2020 C-ThREE
    LOJ#2083. 「NOI2016」优秀的拆分
    BZOJ2754: [SCOI2012]喵星球上的点名
    BZOJ4516: [Sdoi2016]生成魔咒
    AtCoder Beginner Contest 146解题报告
    拉格朗日插值复习笔记
    对于求解单峰函数最值问题的探讨
    BZOJ5509: [Tjoi2019]甲苯先生的滚榜
    面试技巧
    性能案例分析 | MAT分析内存泄露
  • 原文地址:https://www.cnblogs.com/linruitao/p/15067873.html
Copyright © 2020-2023  润新知