Java设计模式之状态模式

作者:tianClassmate 时间:2022-05-08 07:24:25 

实际开发中订单往往都包含着订单状态,用户每进行一次操作都要切换对应的状态,而每次切换判断当前的状态是必须的,就不可避免的引入一系列判断语句,为了让代码更加清晰直观,我们引入今天的主角——状态模式。

一、概念理解

假设订单状态有,下单、发货、确认收货,如果用户确认收货,在常规编程中就要判断当前用户的状态,然后再修改状态,如果这种情况下使用状态模式。

将各个状态都抽象成一个状态类,比如下单状态类、发货状态类、确认收货类,在状态类中处理相应的逻辑和控制下一个状态,在定义一个环境类,定义初始状态,并控制切换状态。

在状态模式中应该包含着三个角色:

环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,这个类持有State接口,负责保持并切换当前的状态。

抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。

具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。

以下为状态模式的类图,看起来是很直观的,理解起来也简单,我们需要说明的是状态模式的类图和策略模式的类图长的一样,但写起来状态模式比策略模式要难。

Java设计模式之状态模式

我们要注意这段话,在状态模式中,类的行为是基于它的状态改变的,状态之间的切换,在状态A执行完毕后自己控制状态指向状态B,状态模式是不停的切换状态执行。这也是状态模式和策略模式不一样的地方。

另外在状态模式中,状态A到B是由自己控制的,而不是由客户端来控制,这是状态模式和策略模式最显著的特征。

我们基于订单状态案例实现demo。

二、案例实现

抽象状态:

定义统一的状态切换方法

/**
* 抽象状态
* @author tcy
* @Date 20-09-2022
*/
public abstract class OrderStateAbstract {
   protected Context context;

public void setContext(Context context) {
       this.context = context;
   }
       /**
        * 状态切换
        */
   public abstract void handle();

}

具体状态-订单付款:

实现状态接口,处理相应的逻辑,并定义下一个状态

/**
* 订单付款
* @author tcy
* @Date 21-09-2022
*/
public class OrderStatePay extends OrderStateAbstract {
  @Override
   public void handle() {
       System.out.println("订单已支付,执行下个状态...");
       context.changeState(new OrderStateOut());

}
}

具体状态-订单发货

/**
* 订单发货
* @author tcy
* @Date 21-09-2022
*/
public class OrderStateOut extends OrderStateAbstract {
    @Override
   public void handle() {
       System.out.println("订单已经发货,开始下一状态...");
       context.changeState(new OrderStateSubmit());
   }
}

具体状态-订单确认收货

/**
* 订单提交
* @author tcy
* @Date 21-09-2022
*/
public class OrderStateSubmit extends OrderStateAbstract {
   @Override
   public void handle() {
       System.out.println("订单已经确认收货...");
   }
}

环境类:

持有最新状态,并调用具体的状态切换方法

/**
* 环境类
* @author tcy
* @Date 20-09-2022
*/
public class Context {

private OrderStateAbstract state;

//定义环境类的初始状态
   public Context() {
       this.state = new OrderStatePay();
       state.setContext(this);
   }

//状态切换
   public void changeState(OrderStateAbstract state) {
       this.state = state;
       this.state.setContext(this);
   }

/**
    * 审批通过请求
    */
   public void request() {
       this.state.handle();
   }
}

客户端调用:

/**
* @author tcy
* @Date 20-09-2022
*/
public class Client {
   public static void main(String[] args) {

//创建环境
       Context context = new Context();
       //订单付款
       context.request();
       //订单发货
       context.request();
       //订单付款
       context.request();

}
}

状态模式客户端调用比较简单,由状态内部类进行状态切换。

三、总结

很多博客都将策略模式的案例代码当做状态模式来讲解,这是不正确的,读者可以参考策略模式两篇做对比学习,认真体会他们之间的区别。

在实际开发中,当控制一个对象状态转换的条件表达式过于复杂时,就可以使用状态模式把相关“判断逻辑”提取出来,用各个不同的类进行表示。

系统处于哪种情况,直接使用相应的状态类对象进行处理,这样能把原来复杂的逻辑判断简单化,消除了 if-else、switch-case 等冗余语句,代码更有层次性,并且具备良好的扩展力。

比如审批流程,我们案例也仅仅是用于订单流程做例子,在实际开发中并不会使用这种方式处理订单,因为订单的处理逻辑实际上并不是那么复杂,引入状态模式反而增加了更多的类,造成系统更加的复杂,这也是设计模式最显著的缺点。

来源:https://www.cnblogs.com/tianClassmate/p/16733554.html

标签:Java,设计,状态,模式
0
投稿

猜你喜欢

  • Java验证码功能的实现方法

    2023-07-05 21:28:21
  • 轻松实现Android自定义九宫格图案解锁

    2023-09-20 00:32:52
  • C#基于简单工厂模式实现的计算器功能示例

    2023-06-19 12:40:10
  • SpringBoot+WebSocket实现多人在线聊天案例实例

    2022-08-22 11:53:08
  • MyBatis-Plus实现2种分页方法(QueryWrapper查询分页和SQL查询分页)

    2021-08-12 09:52:55
  • c# this关键字用法代码详解

    2022-06-07 15:22:09
  • android解析JSON数据

    2022-10-17 04:55:40
  • 基于XSLT调试的相关问题

    2022-11-01 14:22:53
  • c#使用file.copy实现文件备份示例

    2021-06-03 05:13:13
  • servlet上传文件实现代码详解(四)

    2021-09-04 21:17:23
  • Java Spring的核心与设计思想你知道吗

    2021-08-30 11:18:03
  • C语言运用函数指针数组实现计算器功能

    2023-10-01 18:45:25
  • java实现简单斗地主(看牌排序)

    2023-09-12 14:42:40
  • 全局记录Feign的请求和响应日志方式

    2021-08-19 18:48:02
  • Java模拟计算机的整数乘积计算功能示例

    2022-01-30 19:25:51
  • Android仿优酷圆形菜单学习笔记分享

    2023-07-31 06:02:31
  • Android资源文件与层次式导航超详细讲解

    2022-07-14 16:28:22
  • java简单列出文件夹下所有文件的方法

    2022-12-23 19:25:05
  • C#如何使用Task执行异步操作

    2023-01-12 03:34:41
  • 浅析C# 装箱和拆箱

    2022-02-06 17:43:27
  • asp之家 软件编程 m.aspxhome.com