详解设计模式:状态模式
创始人
2024-04-17 15:33:48
0

状态模式(State Pattern)也被称为状态机模式(State Machine Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。

在状态模式 类的行为是基于它的状态改变的。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。状态模式 对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

本篇文章内容包括:关于状态模式、状态模式 Demo


文章目录

    • 一、关于状态模式
        • 1、关于状态模式
        • 2、关于状态模式的构成
        • 3、关于状态模式UML
        • 4、关于状态模式的应用场景
        • 5、关于状态模式的优缺点
    • 二、状态模式 Demo
        • 1、Demo 设计
        • 2、Demo 实现
        • 3、Demo 测试


一、关于状态模式

1、关于状态模式

状态模式(State Pattern)也被称为状态机模式(State Machine Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。

在状态模式 类的行为是基于它的状态改变的。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。状态模式 对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

2、关于状态模式的构成

状态模式主要包含以下 3 种角色:

  • 环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换;
  • 抽象状态(State)角色:定义一个接口,用以封装环境中的特定状态所对应的行为,可以有一个或多个行为;
  • 具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。

3、关于状态模式UML

image-20221203202933112

4、关于状态模式的应用场景

通常在以下情况下可以考虑使用状态模式。

  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。

5、关于状态模式的优缺点

# 状态模式优点

  • 可以将不同的状态隔离;
  • 每个状态都是一个单独的类;
  • 可以将各种状态的转换逻辑,分布到状态的子类中,减少相互依赖;
  • 增加新状态,操作简单;

# 状态模式缺点

  • 如果状态数量比较多,状态类的数量会增加,业务场景系统变得很复杂;
  • 如果业务中某个对象由几十上百个状态,就会很复杂,这时就需要对状态进行拆分处理。

二、状态模式 Demo

1、Demo 设计

我们此处可以设计一个多线程的状态转换程序,多线程存在 新建、就绪、运行、阻塞和死亡状态。各种状态当遭到相关方法调用/事件触发时会向其他状态转换。

2、Demo 实现

# ThreadContext 环境类(Context)角色

public class ThreadContext {private ThreadState state;ThreadContext() {state = new New();}public ThreadState getState() {return state;}public void setState(ThreadState state) {this.state = state;}public void start() {((New) state).start(this);}public void getCpu() {((Runnable) state).getCpu(this);}public void suspend() {((Running) state).suspend(this);}public void stop() {((Running) state).stop(this);}public void resume() {((Blocked) state).resume(this);}
}

# ThreadState 抽象状态(State)角色

public abstract class ThreadState {/*** 状态名*/protected  String stateName;
}

# 新建 New 具体状态(Concrete State)角色

public class New extends ThreadState {public New() {stateName = "新建";System.out.println("线程状态:新建");}public void start(ThreadContext context) {System.out.println("调用 start 方法");if ("新建".equals(stateName)) {context.setState(new Runnable());} else {System.out.println("当前线程不是 New 状态,无法调用 start");}}
}

# 就绪 Runnable 具体状态(Concrete State)角色

public class Runnable extends ThreadState{public Runnable() {stateName = "就绪";System.out.println("线程状态:就绪");}public void getCpu(ThreadContext context) {System.out.println("调用 getCpu 方法");if ("就绪".equals(stateName)) {context.setState(new Running());} else {System.out.println("当前线程不是 就素 状态,无法调用获取 '获取CPU' 的方法");}}
}

# 运行 Running 具体状态(Concrete State)角色

public class Running extends ThreadState {public Running() {stateName = "运行";System.out.println("线程状态:运行");}/*** 挂起* @param context ThreadContext*/public void suspend(ThreadContext context) {System.out.println("调用 suspend 方法");if ("运行".equals(stateName)) {context.setState(new Blocked());} else {System.out.println("当前线程不是 运行 状态,无法调用获取 '挂起' 的方法");}}/*** 停止* @param context ThreadContext*/public void stop(ThreadContext context) {System.out.println("调用 stop 方法");if ("运行".equals(stateName)) {context.setState(new Dead());} else {System.out.println("当前线程不是 运行 状态,无法调用获取 '停止' 的方法");}}
}

# 阻塞 Blocked 具体状态(Concrete State)角色

public class Blocked extends ThreadState {public Blocked() {stateName = "阻塞";System.out.println("线程状态:阻塞");}/*** 状态恢复* @param context ThreadContext*/public void resume(ThreadContext context) {System.out.println("调用 resume 方法");if ("阻塞".equals(stateName)) {context.setState(new Runnable());} else {System.out.println("当前线程不是 阻塞 状态,无法调用获取 '状态恢复' 的方法");}}
}

# 死亡 Dead 具体状态(Concrete State)角色

public class Dead extends ThreadState {public Dead() {stateName = "死亡";System.out.println("线程状态:死亡");}
}

3、Demo 测试

public class Client {public static void main(String[] args) {ThreadContext context = new ThreadContext();context.start();context.getCpu();context.suspend();context.resume();context.getCpu();context.stop();}
}

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...