19、State 状态模式
“人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换。就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流动,冰可以雕刻,蒸汽可以扩散。
1、State 状态模式
状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客户端的使用。在实际开发中,状态模式具有较高的使用频率,在工作流和游戏开发中状态模式都得到了广泛的应用,例如公文状态的转换、游戏中角色的升级等。
定义
当一个对象的内部状态改变时,允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态转换的条件过于复杂的情况。吧状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的控制逻辑转换。当然,如果这个状态逻辑很简单,就没必要用状态模式了。
意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
2、示例代码
酒店客房房间状态变化
2.1、原始方案
if (state == "空闲") {
if (预定房间) {
预定操作;
state = "预定";
}else if(入住房间) {
入住操作;
state = "入住";
}
} else if(state == "预定") {
if (取消预定) {
取消预定操作;
state = "空闲";
}else if(入住房间) {
入住操作;
state = "入住";
}
} else {
if (退房) {
退房操作;
state = "空闲";
}else if(续房) {
入住操作;
state = "入住";
}
}
2.2、使用state模式
1、State状态接口,定义一个状态的行为
/**
* User:tumbler
* Desc:状态模式--状态接口
*/
public interface State {
void handle();
}
2、具体状态ConcreteState,实现State接口。空闲、预定、入住
/**
* User:tumbler
* Desc:状态模式--具体状态ConcreteState--空闲
*/
public class FreeState implements State {
@Override
public void handle() {
System.out.println("房间空闲!!!");
}
}
/**
* User:tumbler
* Desc:状态模式--具体状态ConcreteState--预定
*/
public class BookedState implements State {
@Override
public void handle() {
System.out.println("房间已预订!!!");
}
}
/**
* User:tumbler
* Desc:状态模式--具体状态ConcreteState--空闲
*/
public class CheckedState implements State {
@Override
public void handle() {
System.out.println("房间已入住!!!");
}
}
3、测试
/**
* User:tumbler
* Desc:状态模式--测试
*/
public class Client {
public static void main(String[] args) {
Context context = new Context();
context.setState(new FreeState());
context.setState(new CheckedState());
}
}
运行结果如下:
修改状态。。。
房间空闲!!!
修改状态。。。
房间已入住!!!
3、State类图
在State模式中有以下登场角色。
◆State(状态)State角色表示状态,定义了根据不同状态进行不同处理的接口( API)。该接口( API)是那些处理内容依赖于状态的方法的集合。在示例程序中,由State接口扮演此角色。
◆ConcreteState (具体状态)ConcreteState角色表示各个具体的状态,它实现了State接口。在示例程序中,由DayState类和NightState类扮演此角色。
◆Context (状况、前后关系、上下文)Context角色持有表示当前状态的ConcreteState角色。此外,它还定义了供外部调用者使用State模式的接口( API)。在示例程序中,由Context接口和SafeFrame类扮演此角色。这里稍微做一下补充说明。在示例程序中,Context 角色的作用被Context接口和SafeFrame类分担了。具体而言,Context接口定义了供外部调用者使用State模式的接口( API), 而SafeFrame类则持有表示当前状态的ConcreteState角色。
4、小结
优缺点
主要优点
状态模式的主要优点如下:
(1) 封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
(2) 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
(3) 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
(4) 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
主要缺点
状态模式的主要缺点如下:
(1) 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
(2) 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
(3) 状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
适用场景
在以下情况下可以考虑使用状态模式:
(1) 对象的行为依赖于它的状态(如某些属性值),状态的改变将导致行为的变化。
(2) 在代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,并且导致客户类与类库之间的耦合增强。
公众号:发哥讲
这是一个稍偏基础和偏技术的公众号,甚至其中包括一些可能阅读量很低的包含代码的技术文,不知道你是不是喜欢,期待你的关注。
如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~
● 扫码关注我们
据说看到好文章不推荐的人,服务器容易宕机!
本文版权归发哥讲和博客园共有,原创文章,未经允许不得转载,否则保留追究法律责任的权利。
19、State 状态模式的更多相关文章
- Java设计模式(19)状态模式(State模式)
State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式 State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If else ...
- C++设计模式-State状态模式
State状态模式作用:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. UML图如下: State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为. ...
- State状态模式
1.简介 在日常开发中,某些对象的状态如果发生改变,对应的行为也将发生改变,那么如何在运行时根据对象的状态动态的改变对象的行为,同时不产生紧耦合关系(即使用if else或者swith所带来的紧耦合关 ...
- 设计模式---状态变化模式之state状态模式(State)
前提:状态变化模式 在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案. 典型模式 状态模式:Stat ...
- 设计模式21:State 状态模式(行为型模式)
State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. ...
- 设计模式C++学习笔记之十九(State状态模式)
19.1.解释 概念:允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类. main(),客户 CLiftState,电梯状态抽象类 CCloseingState,电梯门关闭 ...
- 程序设计模式 —— State 状态模式
我应该如何阅读? 本文将使用优雅的文字风格来告诉你什么是状态模式. 注意: 1.在阅读本文之前请保证你已经掌控了 面对对象的思想与 多态的基本概念,否则将难以理解. 2.本文实现将用C++实现,你不一 ...
- JAVA设计模式--State(状态模式)
状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...
- 设计模式之 State 状态模式
状态模式的核心在于 1. 状态的转换导致行为(Handle)的差异,比如人的状态是饿的时候,吃(Handle)的行为是2个馒头,人状态是不太饿的时候,吃(Handle)的行为是半个馒头 2. Stat ...
随机推荐
- 数据可视化之powerBI基础(十七)掌握PowerBI按列排序,再也不用担心顺序错乱了
https://zhuanlan.zhihu.com/p/64421933 经常有朋友问,当把文本字段放到坐标轴或者切片器上,显示的顺序都乱了,完全不是自己想要的,就像下面这些, ↑月份坐标轴 ↑星期 ...
- Django之Model、Form、ModelForm区别
本节内容: 1:Model https://www.cnblogs.com/shuai1991/p/10844662.html 2:Form ...
- MySQL索引——总结篇
MySQL索引 MySQL索引 数据库的三范式,反模式 零碎知识 索引 索引原理 B Tree索引 B+Tree索引 B Tree 与 B+Tree的比较 聚集索引和辅助索引 聚集索引的注意事项 索引 ...
- Docker 基础知识 - 使用卷(volume)管理应用程序数据
卷(volumes)是 Docker 容器生产和使用持久化数据的首选机制.绑定挂载(bind mounts)依赖于主机的目录结构,卷(volumes)完全由 Docker 管理.卷与绑定挂载相比有几个 ...
- Python Ethical Hacking - TROJANS Analysis(2)
DOWNLOAD & EXECUTE PAYLOAD A generic executable that downloads & executes files. Disadvantag ...
- 关于Java8的精心总结
前言 最近公司里比较新的项目里面,看到了很多关于java8新特性的用法,由于之前自己对java8的新特性不是很了解也没有去做深入研究,所以最近就系统的去学习了一下,然后总结了一篇文章第一时间和大家 ...
- Vue全家桶之一Vue(基础知识篇)
全家桶:Vue本身.状态管理.路由. 异步组件:
- three.js 数学方法之Vector3
今天郭先生来说一说three.js的Vector3,该类表示的是一个三维向量(3D vector). 一个三维向量表示的是一个有顺序的.三个为一组的数字组合(标记为x.y和z),可被用来表示很多事物, ...
- deepin换源
python的pip源 pip install pip -U pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/sim ...
- 第三节:Centos下安装Mysql5.6数据库
1.下载mysql5.6版本 [官网-需要什么版本自己去找]https://dev.mysql.com/downloads/mysql/5.6.html [版本]linux通用 cd /usr/loc ...