设计模式之状态模式

一、什么是状态模式

状态模式,对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

状态模式,属于行为型设计模式。

二、状态模式类图

设计模式之状态模式插图

三、状态模式角色

  • 抽象状态角色(State): 定义一个接口以封装使用上下文环境的一个特定状态相关的行为。
  • 具体状态角色(ConcreteState): 实现抽象状态定义的接口。
  • 环境角色(Context): 定义了客户端需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的ConcreteState对象来处理。

四、状态模式优缺点

优点:

  1. 将所有与某个状态有关的行为放到一个类中,并且将不同状态的行为分割开来,满足“单一职责原则”。
  2. 将不同的状态引入单独的对象中会使得状态转换变得更加明确,减少对象间的相互依赖。
  3. 有利于程序的扩展。新增状态可以通过新增状态子类来完成,满足”开闭原则“。

缺点:

  1. 增加了系统的类与对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。

五、状态模式demo示例

1、Demo需求

以电商平台订单状态为例,使用状态模式实现订单状态流转,订单状态:待支付、待发货、已发货、已收货。

2、抽象类定义

/**
  * @Description: 抽象状态角色:抽象订单状态类
  **/ public abstract class OrderState {

     /**
      * 待支付状态
      *
      * @param context
      */     public abstract void unpay(OrderContext context);
 
     /**
      * 待发货状态
      *
      * @param context
      */     public abstract void undelivered(OrderContext context);
 
     /**
      * 已发货状态
      *
      * @param context
      */     public abstract void delivered(OrderContext context);
 
     /**
      * 已收货状态
      *
      * @param context
      */     public abstract void received(OrderContext context);
 }

3、实现类定义

/**
  * @Description: 具体订单状态角色:待支付状态
  **/ public class UnpayState extends OrderState {

     @Override
     public void unpay(OrderContext context) {
         System.out.println("订单待支付状态");
         context.setState(new UndeliveredState());
     }
 
     @Override
     public void undelivered(OrderContext context) {
         System.out.println("订单待支付状态,请先支付");
     }
 
     @Override
     public void delivered(OrderContext context) {
         System.out.println("订单待支付状态,请先支付");
     }
 
     @Override
     public void received(OrderContext context) {
         System.out.println("订单待支付状态,请先支付");
     }
 }
/**
  * @Description: 具体订单状态角色:待发货状态类
  **/ public class UndeliveredState extends OrderState {

     @Override
     public void unpay(OrderContext context) {
         System.out.println("订单已支付,请不要重复支付");
     }
 
     @Override
     public void undelivered(OrderContext context) {
         System.out.println("订单已支付等待发货啦");
         context.setState(new DeliveredState());
     }
 
     @Override
     public void delivered(OrderContext context) {
         System.out.println("订单待发货,请先发货");
     }
 
     @Override
     public void received(OrderContext context) {
         System.out.println("订单待发货,请先发货");
     }
 }
/**
  * @Description: 具体订单状态角色:已发货状态类
  **/ public class DeliveredState extends OrderState {

     @Override
     public void unpay(OrderContext context) {
         System.out.println("订单已支付,请不要重复支付");
     }
 
     @Override
     public void undelivered(OrderContext context) {
         System.out.println("订单已发货,请不要重复发货");
     }
 
     @Override
     public void delivered(OrderContext context) {
         System.out.println("订单已发货啦");
         context.setState(new ReceivedState());
     }
 
     @Override
     public void received(OrderContext context) {
         System.out.println("订单已发货,未收到");
     }
 }
/**
  * @Description: 具体订单状态角色:已收货状态类
  **/ public class ReceivedState extends OrderState {

     @Override
     public void unpay(OrderContext context) {
         System.out.println("订单已支付,请不要重复支付");
     }
 
     @Override
     public void undelivered(OrderContext context) {
         System.out.println("订单已发货,请不要重复发货");
     }
 
     @Override
     public void delivered(OrderContext context) {
         System.out.println("订单已发货啦");
     }
 
     @Override
     public void received(OrderContext context) {
         System.out.println("订单已收货啦");
     }
 }

4、上下文类定义

/**
  * @Description: 环境角色:订单上下文类
  **/ public class OrderContext {

     // 抽象订单状态对象
     private OrderState state;
 
     public void setState(OrderState state) {
         this.state = state;
     }
 
     /**
      * 订单待支付状态
      */     public void unpay() {
         state.unpay(this);
     }
 
     /**
      * 订单待发货状态
      */     public void undelivered() {
         state.undelivered(this);
     }
 
     /**
      * 订单已发货状态
      */     public void delivered() {
         state.delivered(this);
     }
 
     /**
      * 订单已收货状态
      */     public void received() {
         state.received(this);
     }
 }

5、测试

/**
  * @Description: 状态模式客户端测试类
  **/ public class Client {
 
     public static void main(String[] args) {
         OrderContext context = new OrderContext();
         // 1.订单待支付状态
         context.setState(new UnpayState());
         context.unpay();
         // 2.订单待发货状态
         context.setState(new UndeliveredState());
         context.undelivered();
         // 3.订单已发货状态
         context.setState(new DeliveredState());
         context.delivered();
         // 3.订单已收货状态
         context.setState(new ReceivedState());
         context.received();
     }
 }

控制台日志:

订单待支付状态
订单已支付等待发货啦
订单已发货啦
订单已收货啦

发表评论