设计模式之状态模式

Posted ProChick

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之状态模式相关的知识,希望对你有一定的参考价值。

1.简要概述

  • 状态模式属于行为型设计模式。
  • 状态模式就是说将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为。
  • 状态模式用于解决系统中复杂对象的状态转换问题,并对于不同状态下的不同行为进行封装。
  • 状态模式允许在对象的内部状态发生改变时,对它的行为也进行相应的改变。

2.模式结构

👉通常由一个环境类( 通常是一个具体的对象,负责维护对象的状态实例,里面定义了当前对象所属的状态信息 ),一个状态接口( 负责定义接口方法,以用来封装与Context类的一个特定状态下的行为逻辑 ),多个具体的状态类( 负责实现Context类对象的某个具体状态对应的行为逻辑 ),一个客户类( 负责对环境类进行调用,完成对象不同状态的之间的转换操作)共同组成。

3.实现代码

举例 💡 :我们知道交通信号灯有三种状态:红灯、黄灯、绿灯,不同的状态代表着应该去执行不同的行为,那么当信号灯状态发生改变时,行为也应该随之改变。所以信号灯状态的转换过程,我们就可以使用状态模式进行处理。

交通信号灯(环境类)

public class SignalLight {
	private LightState currentState;
	
    private LightState red;
    private LightState yellow;
    private LightState green;
    
    public SignalLight(){
        red = new RedState(this);
        yellow = new YellowState(this);
        green = new GreenState(this);
    }
    
	public void setState(LightState state){
		this.currentState = state;
	}
	
	public void getCurrentState() {
		currentState.behave();
	}
}

信号灯状态(状态接口)

public interface LightState {
    // 定义行为方法
	void behave();
}

红灯(具体的状态类)

public class RedState implements LightState{
	private SignalLight signalLight;
    
    public RedState(SignalLight signalLight){
        this.signalLight = signalLight;
    }
    
    @Override
	public void behave() {
		System.out.println("当前处于红灯状态,禁止前行");
        signalLight.setState(signalLight.yellow);
	}
}

黄灯(具体的状态类)

public class YellowState implements LightState{
	private SignalLight signalLight;
    
    public RedState(SignalLight signalLight){
        this.signalLight = signalLight;
    }
    
    @Override
	public void behave() {
		System.out.println("当前处于黄灯状态,请等待");
	}
}

绿灯(具体的状态类)

public class GreenState implements LightState{
	private SignalLight signalLight;
    
    public RedState(SignalLight signalLight){
        this.signalLight = signalLight;
    }
    
    @Override
	public void behave() {
		System.out.println("当前处于绿灯状态,允许前行");
        signalLight.setState(signalLight.yellow);
	}
}

客户类

// 测试客户端
public class LightClient{
    public static void main(String[] args) {
        SignalLight signalLight = new SignalLight();
        
        // 设置为红灯状态
        signalLight.set(signalLight.red);
        signalLight.getCurrentState(); //当前处于红灯状态,禁止前行
        signalLight.getCurrentState(); //当前处于黄灯状态,请等待
        
        // 设置为绿灯状态
        signalLight.set(signalLight.green);
        signalLight.getCurrentState(); //当前处于绿灯状态,允许前行
        signalLight.getCurrentState(); //当前处于黄灯状态,请等待
    }
}

4.优点好处

  • 在状态模式中,对象状态转换的细节对于客户端而言是透明的,所以方便了客户端的调用。
  • 在状态模式中,避免了过多的条件分支判断语句,使得代码结构清晰且具有很强的可读性。
  • 在状态模式中,每一个状态所对应的状态类都只负责实现一项业务功能,符合单一职责原则。
  • 在状态模式中,容易对状态进行动态的添加和删除,符合开闭原则。

5.缺点弊端

  • 由于每一种状态都要对应一个状态类进行维护,所以当系统中的某个对象拥有非常多的状态时,那么就会产生很多的状态类,使得系统变得复杂,增加了维护难度。
  • 使用状态模式需要将事物的不同状态以及对应的行为拆分出来,但是如果遇到业务逻辑比较复杂的代码,我们很容易就把状态和行为弄混淆,所以不利于拆分。

6.应用场景

  • 当我们系统代码中包含大量与对象状态有关的条件语句,比如庞大的分支判断语句,且这些分支都依赖于该对象的某种状态的时候,就可以使用状态模式。
  • 当系统中对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为的时候,就可以使用状态模式。
  • 当系统中的某个对象有很多状态需要进行管理,并且状态之间会经常进行切换,然后执行不同行为的时候,就可以使用状态模式。

7.应用示例

电商项目源码中的订单状态管理

  1. 首先在电商平台中,一个订单从生成到结束,往往会经历下面的一系列流程。

  2. 对于上述流程中的订单类,我们就可以把它当作是状态模式中的环境类,里面聚合了订单的各种状态对象。

  3. 每个订单的状态都会对应着不同的业务行为,当状态发生改变时,对应的行为也会发生改变,比如:待付款状态需要进行付款操作、已付款状态需要进行信息反馈操作、退款状态需要进行退款操作等等。

  4. 所以从上面的描述过程来看,电商平台中有关订单状态的管理就是采用的状态模式。

以上是关于设计模式之状态模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之行为型状态模式

Head First设计模式之状态模式

设计模式之状态模式20170712

设计模式之状态模式

java 之 状态模式(大话设计模式)

JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段