二十三种设计模式第二十三篇--状态模式

状态模式,是一种行为模式,在软件开发过程中,对象按照不同的情况做出不同的行为,我们把这样的对象称为具有状态的对象,而把影响对象行为的一个或者多个动态变化的属性称为状态。

对这种具有状态的对象变成,传统的解决方案是,将这些所有可能发生情况全部考虑到,然后使用if-else或者switch-case语句来做状态判断,再进行不同情况的处理。但是这种情况存在一个弊端,就是,条件判断语句会过于浮肿,可读性差,并且不具备拓展性,维护难度也将加大,并且增加新的状态时需要添加新的if-else语句,这违背了"开闭原则",并不利于程序的拓展。

状态模式:它允许对象在内部状态改变时改变其行为。状态模式将状态和对应的行为封装成不同的状态对象,使得对象的行为可以根据不同的状态进行动态切换。

状态模式的核心组成部分包括:

状态接口(State Interface):定义了状态对象的接口,包含了对象在该状态下可以执行的方法。
具体状态类(Concrete State):实现了状态接口,在具体的状态下定义了对象的行为。
环境类(Context):包含了一个状态对象,并维护当前的状态,可以根据不同的状态调用相应的方法。

状态模式的主要优点包括:

将状态和行为分离 :将不同的状态封装成不同的对象,使得状态和行为可以独立变化,提高了代码的灵活性和可维护性。
简化条件语句 :通过状态对象的切换来替代复杂的条件语句,使得代码更加清晰和易懂。
符合开闭原则:增加新的状态类不会修改已有的代码,只需要添加新的状态类和相应的转换规则。

关于状态模式的限制和适用场景:
可能增加对象的数量:每个状态都需要一个对应的状态类,可能会增加对象的数量。
当状态比较少且相对简单时,使用状态模式可能会增加代码的
复杂性。

状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

java 复制代码
/**
 * 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
 */
public interface State {

   //行为动作...
   public void doAction(Context context);

}
java 复制代码
/**
 * 具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
 * 这里代表游戏玩家开始的状态.
 */
public class StartState implements State {
 
   @Override
   public void doAction(Context context) {
      System.out.println("玩家处理于启动状态,开始相应操作");
      //给上下文对象设定对应的状态对象,然后在 context执行对应的操作
      // 这里避免了使用 if...else 这样的判断语句.
      context.setState(this);
   }
 
   @Override
   public String toString(){
      return "开始状态";
   }
}
java 复制代码
/**
 * 环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
 *
 * 状态机
 */
public class Context {
   /**
    *  ******* 状态
    */
   private State state;
 
   public Context(){
      state = null;
   }

   //******状态修改
   public void setState(State state){
      this.state = state;
      //TODO:在这里可以加入 状态修改后的进一步的操作...

      //修改状态  -> 触发事件   -> 消息通知   -> 操作  -> 状态改变.
      //    a   ->  e1       ->    b
      //    b   ->   e2      ->    c


   }
 
   public State getState(){
      return state;
   }
}
java 复制代码
public class StatePatternDemo {
   public static void main(String[] args) {

      Context context = new Context();
      //注意比较:  以下状态发生变化时,无须要用  if..else做状态判断.

      //设置状态为开始.
      StartState startState = new StartState();
      startState.doAction(context);
 
      System.out.println(context.getState().toString());

      //修改状态为  stop
      StopState stopState = new StopState();
      stopState.doAction(context);
 
      System.out.println(context.getState().toString());
   }
}
java 复制代码
/**
 * 具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
 * 停止状态
 */
public class StopState implements State {
 
   @Override
   public void doAction(Context context) {
      System.out.println("Player is in stop state");
      //给上下文对象设定对应的状态对象,然后在 context执行对应的操作
      // 这里避免了使用 if...else 这样的判断语句.
      context.setState(this); 
   }
 
   @Override
   public String toString(){
      return "Stop State";
   }
}

路才刚刚开始走,怎么能半路放弃呢?听我所听,做我想做,梦我想梦,也许几年后我看到这句话会把他删掉,也许他就这么挂在这里,一直挂着。我与众生皆为凡人,无高低贵贱,他擅他长,吾擅吾长,何须羡慕他人等?身在其位,专攻其事,如若不善,辞职跑路!何须压抑与心之久,于己不快哉,长路漫漫有人陪同吾亦乐之,无人陪同吾亦独行,彼岸花开,终有一日,吾亦赏之。

相关推荐
敲代码的约德尔人9 小时前
JavaScript 设计模式完全指南
javascript·设计模式
I'm Jie12 小时前
Swagger UI 本地化部署,解决 FastAPI Swagger UI 依赖外部 CDN 加载失败问题
python·ui·fastapi·swagger·swagger ui
爱学习的程序媛13 小时前
【Web前端】优化Core Web Vitals提升用户体验
前端·ui·web·ux·用户体验
爱学习的程序媛13 小时前
【Web前端】前端用户体验优化全攻略
前端·ui·交互·web·ux·用户体验
han_14 小时前
JavaScript设计模式(二):策略模式实现与应用
前端·javascript·设计模式
紫丁香14 小时前
Selenium自动化测试详解1
python·selenium·测试工具·ui
GISer_Jing14 小时前
前端组件库——shadcn/ui:轻量、自由、可拥有,解锁前端组件库的AI时代未来
前端·人工智能·ui
阿珊和她的猫17 小时前
微信小程序静默授权异步问题的处理方案
微信小程序·状态模式·notepad++
rjc_lihui17 小时前
IntelliSense: 无法打开 源 文件 “ui_mainwindow.h“ demo\qtdemosrc\mainwindow
ui
前端不太难1 天前
ArkUI 的页面生命周期详解
状态模式