详解设计模式:状态模式
创始人
2024-03-19 17:43:49
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();}
}

相关内容

热门资讯

东营区司法局:充电蓄能强本领,... 为进一步加强全区专职人民调解队伍建设,提升人民调解工作整体水平,东营区司法局于12月25日成功举办全...
捍卫品牌正当权益,比亚迪起诉自... 比亚迪起诉自媒体“龙哥讲电车”等账号一审胜诉,法院认定他们编造虚假信息、损害比亚迪声誉,判决其停止侵...
民进党当局对所谓“两岸关系条例... 12月26日,台湾《中国时报》报道,陆委会近日推动所谓“两岸人民关系条例”四项修正,包含:公务员赴陆...
住户养百余只猫引发邻里纠纷 北... 12月19日,随着住户曹某将100余只猫全部迁出,一场发生在北京石景山的邻里纠纷得以实质化解。 一住...
新修订的《河南省征兵工作条例》... 日前,省人大常务委员会发布公告,新修订的《河南省征兵工作条例》自2026年1月1日起施行。 据省征兵...
云南出台重要条例!明年1月1日... 《云南省县级人民代表大会常务委员会街道工作委员会工作条例》将于2026年1月1日起施行。12月26日...
第四批生态环境损害赔偿十大典型... 12月26日,生态环境部联合住房城乡建设部、水利部、农业农村部,共同发布第四批生态环境损害赔偿十大典...
海峡创新(300300)披露对... 截至2025年12月26日收盘,海峡创新(300300)报收于17.15元,较前一交易日上涨0.94...
年度“法规体检”报告亮相 备案... 中新社北京12月26日电 (记者 谢雁冰)督促纠正要求残疾人机动轮椅车登记应当具有本市常住户籍问题,...