【设计模式】【行为型模式(Behavioral Patterns)】之状态模式(State Pattern)
1. 设计模式原理说明
状态模式(State Pattern) 是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这个模式的核心思想是使用不同的类来表示不同的状态,每个状态类都封装了与该状态相关的特定行为。当对象的状态发生改变时,对象会切换到另一个状态对象,从而改变了它的行为。
主要角色
- Context(上下文):定义客户感兴趣的接口,维护一个对当前状态对象的引用。
- State(抽象状态):定义一个接口,用以封装与Context的一个特定状态相关的行为。
- ConcreteState(具体状态):实现State接口,每种状态都对应一个具体的状态类,封装了与该状态相关的特定行为。
2. UML 类图及解释
UML 类图
+-----------------+
| Context |
|-----------------|
| - state: State |
| + setState(state: State) |
| + request() |
+-----------------+^||v
+-----------------+
| State |
|-----------------|
| + handle(context: Context) |
+-----------------+^||v
+-----------------+
| ConcreteStateA |
|-----------------|
| + handle(context: Context) |
+-----------------+^||v
+-----------------+
| ConcreteStateB |
|-----------------|
| + handle(context: Context) |
+-----------------+
类图解释
- Context:定义客户感兴趣的接口,维护一个对当前状态对象的引用。当状态变化时,调用
setState
方法更新当前状态。 - State:定义一个接口,用以封装与Context的一个特定状态相关的行为。
- ConcreteStateA 和 ConcreteStateB:实现State接口,每种状态都对应一个具体的状态类,封装了与该状态相关的特定行为。
3. 代码案例及逻辑详解
Java 代码案例
// 抽象状态
interface State {void handle(Context context);
}// 具体状态 A
class ConcreteStateA implements State {@Overridepublic void handle(Context context) {System.out.println("Current state is ConcreteStateA");context.setState(new ConcreteStateB());}
}// 具体状态 B
class ConcreteStateB implements State {@Overridepublic void handle(Context context) {System.out.println("Current state is ConcreteStateB");context.setState(new ConcreteStateA());}
}// 上下文
class Context {private State state;public Context(State state) {this.state = state;}public void setState(State state) {this.state = state;}public void request() {state.handle(this);}
}// 客户端
public class Client {public static void main(String[] args) {Context context = new Context(new ConcreteStateA());context.request(); // 输出: Current state is ConcreteStateAcontext.request(); // 输出: Current state is ConcreteStateB}
}
C++ 代码案例
#include <iostream>// 抽象状态
class State {
public:virtual void handle(Context* context) = 0;
};// 具体状态 A
class ConcreteStateA : public State {
public:void handle(Context* context) override {std::cout << "Current state is ConcreteStateA" << std::endl;context->setState(new ConcreteStateB());}
};// 具体状态 B
class ConcreteStateB : public State {
public:void handle(Context* context) override {std::cout << "Current state is ConcreteStateB" << std::endl;context->setState(new ConcreteStateA());}
};// 上下文
class Context {
private:State* state;
public:Context(State* state) : state(state) {}void setState(State* state) {delete this->state;this->state = state;}void request() {state->handle(this);}
};// 客户端
int main() {Context* context = new Context(new ConcreteStateA());context->request(); // 输出: Current state is ConcreteStateAcontext->request(); // 输出: Current state is ConcreteStateBdelete context;return 0;
}
Python 代码案例
# 抽象状态
class State:def handle(self, context):pass# 具体状态 A
class ConcreteStateA(State):def handle(self, context):print("Current state is ConcreteStateA")context.set_state(ConcreteStateB())# 具体状态 B
class ConcreteStateB(State):def handle(self, context):print("Current state is ConcreteStateB")context.set_state(ConcreteStateA())# 上下文
class Context:def __init__(self, state):self.state = statedef set_state(self, state):self.state = statedef request(self):self.state.handle(self)# 客户端
if __name__ == "__main__":context = Context(ConcreteStateA())context.request() # 输出: Current state is ConcreteStateAcontext.request() # 输出: Current state is ConcreteStateB
Go 代码案例
package mainimport ("fmt"
)// 抽象状态
type State interface {handle(context *Context)
}// 具体状态 A
type ConcreteStateA struct{}func (s *ConcreteStateA) handle(context *Context) {fmt.Println("Current state is ConcreteStateA")context.setState(&ConcreteStateB{})
}// 具体状态 B
type ConcreteStateB struct{}func (s *ConcreteStateB) handle(context *Context) {fmt.Println("Current state is ConcreteStateB")context.setState(&ConcreteStateA{})
}// 上下文
type Context struct {state State
}func (c *Context) setState(state State) {c.state = state
}func (c *Context) request() {c.state.handle(c)
}// 客户端
func main() {context := &Context{state: &ConcreteStateA{}}context.request() // 输出: Current state is ConcreteStateAcontext.request() // 输出: Current state is ConcreteStateB
}
4. 总结
状态模式 是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这个模式的核心思想是使用不同的类来表示不同的状态,每个状态类都封装了与该状态相关的特定行为。当对象的状态发生改变时,对象会切换到另一个状态对象,从而改变了它的行为。
主要优点
- 简化对象的操作:将与特定状态相关的行为封装在状态对象中,使上下文对象的操作更加简单。
- 高内聚低耦合:状态对象之间的转换逻辑被封装在状态对象内部,减少了上下文对象的复杂性。
- 易于扩展:新增状态时,只需添加新的状态类,而不需要修改现有的代码。
主要缺点
- 类的膨胀:每增加一个新的状态就需要增加一个新的类,可能导致类的数量急剧增加。
- 状态转换逻辑复杂:状态之间的转换逻辑可能变得复杂,尤其是当状态数量较多时。
适用场景
- 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。
- 当控制一个对象的状态转换的条件表达式过于复杂时。
- 当代码中包含大量与对象状态有关的条件语句时,可以考虑使用状态模式来简化这些条件语句。
相关文章:
【设计模式】【行为型模式(Behavioral Patterns)】之状态模式(State Pattern)
1. 设计模式原理说明 状态模式(State Pattern) 是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这个模式的核心思想是使用不同的类来表示不同的状态,每个状态类都封装了与该状态相关的特定行为。当对象的状态发…...
QML学习 —— 34、视频媒体播放器(附源码)
效果 说明 您可以单独使用MediaPlayer播放音频内容(如音频),也可以将其与VideoOutput结合使用以渲染视频。VideoOutput项支持未转换、拉伸和均匀缩放的视频演示。有关拉伸均匀缩放演示文稿的描述,请参见fillMode属性描述。 播放可能出错问题 出现的问题: DirectS…...
【深度学习|特征增强模块】FFN(前馈神经网络)和E_FFN(增强型前馈神经网络)是transformer特征增强的重要组成部分!
【深度学习|特征增强模块】FFN(前馈神经网络)和E_FFN(增强型前馈神经网络)是transformer特征增强的重要组成部分! 【深度学习|特征增强模块】FFN(前馈神经网络)和E_FFN(增强型前馈神…...
【Qt】控件7
1.QTextEdit的简单使用 使用简单的QTextEdit,获取到的内容显示到标签上 使用textChanged信号 在槽函数中需要获取QTextEdit的内容,对应操作是: QString curorui->textEdit->toPlainText();然后显示到标签上,对应操作是: …...
F12抓包14_修改网页图片网页保存到本地
课程大纲 1、修改网页图片(2种方式二选一) 修改网页图片,需要定位到图片标签,修改<img>标签的属性。2种方法: 1. 修改为网络图片url。缺点:url失效,图片无法显示。 2. 修改为图片base64&a…...
源代码检测,内附实际案例
源代码安全审计是依据国标GB/T 34944-2017、GB/T 34944-2017,结合专业源代码扫描工具对各种程序语言编写的源代码进行安全审计。能够为客户提供包括安全编码规范咨询、源代码安全现状评测、定位源代码中存在的安全漏洞、分析漏洞风险、给出修改建议等一系列服务。 源…...
1138:将字符串中的小写字母转换成大写字母
【题目描述】 给定一个字符串,将其中所有的小写字母转换成大写字母。 【输入】 输入一行,包含一个字符串(长度不超过100,可能包含空格)。 【输出】 输出转换后的字符串。 【输入样例】 helloworld123Ha 【输出样例】…...
《C++ 人工智能模型邂逅云平台:集成之路的策略与要点全解析》
在当今数字化浪潮汹涌澎湃的时代,人工智能无疑是引领技术变革的核心力量。而 C以其卓越的性能和高效的资源利用,成为开发人工智能模型的有力武器。与此同时,云平台所提供的强大计算能力、灵活的存储资源以及便捷的服务部署,为人工…...
【ArcGISPro】Sentinel-2数据处理
错误 默认拉进去只组织了4个波段,但是实际有12个波段 解决方案 数据下载 Sentinel-2 数据下载-CSDN博客 数据处理 数据查看 创建镶嵌数据集 在数据管理工具箱中找到创建镶嵌数据集...
Unity中的简易TCP服务器/客户端
在本文中,我将向你介绍一个在Unity中实现的简单TCP服务器脚本,和一个简单的客户端脚本. 脚本 MyTcpServer 允许Unity应用创建一个TCP服务器,监听客户端的连接、异步处理客户端消息,并通过事件与Unity应用中的其他模块进行通信。 MyTcpServe…...
Spring Boot 3.4 正式发布,结构化日志!
1 从 Spring Boot 3.3 升级到 3.4 1.1 RestClient 和 RestTemplate 新增对 RestClient 和 RestTemplate 自动配置的支持,可用 Reactor Netty 的 HttpClient 或 JDK 的 HttpClient。支持的客户端优先级: Apache HTTP Components (HttpComponentsClient…...
技术文档,they are my collection!
工作 今天这篇文章,献给一直撰写技术文档的自己。我自认为是公司中最爱写文档的人了,我们是一个不到40人的小公司,公司作风没有多么严谨,领导也不会要求我们写技术文档。但是从入职初至今,我一直保持着写技术文档…...
详解Qt之QtMath Qt数学类
文章目录 QtMath详解前言QtMath简介QtMath中的函数1. 三角函数1.1 qSin1.2 qCos 2. 指数与对数函数2.1 qExp2.2 qLn 3. 幂运算与平方根3.1 qPow3.2 qSqrt QtMath的优势1. 一致性与跨平台支持2. 与Qt生态系统集成3. 简洁性 总结 QtMath详解 前言 在C的开发中,数学运…...
人工智能与人类:共创未来的新篇章
数年前,当人工智能还停留在实验室的时候,很少有人能想到它会如此迅速地融入我们的日常生活。如今,从手机上的语音助手,到自动驾驶汽车,从智能家居到医疗诊断,AI的身影无处不在。这让我想起了20世纪初电力普…...
4.6 JMeter HTTP信息头管理器
欢迎大家订阅【软件测试】 专栏,开启你的软件测试学习之旅! 文章目录 前言1 HTTP信息头管理器的位置2 常见的HTTP请求头3 添加 HTTP 信息头管理器4 应用场景 前言 在 JMeter 中,HTTP信息头管理器(HTTP Header Manager)…...
非交换几何与黎曼ζ函数:数学中的一场革命性对话
非交换几何与黎曼ζ函数:数学中的一场革命性对话 非交换几何(Noncommutative Geometry, NCG)是数学的一个分支领域,它将经典的几何概念扩展到非交换代数的框架中。非交换代数是一种结合代数,其中乘积不是交换性的&…...
【设计模式】【行为型模式(Behavioral Patterns)】之观察者模式(Observer Pattern)
1. 设计模式原理说明 观察者模式(Observer Pattern) 是一种行为设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式非常适合处理事件驱动系统&a…...
文件导入-使用java反射修改日期数据
文件导入时,时间类型通常不能直接导出,以下方法为批量处理类中日期类型转字符串类型。 Date/Datetime --> String(yyyy-mm-dd)Field[] declaredFields HrAviationstudentMonitorDTO.class.getDeclaredFields(); for (Field field : declaredFields) …...
【网络安全设备系列】10、安全审计系统
0x00 定义: 网络安全审计系统针对互联网行为提供有效的行为审计、内容审计、行为报警、行为控制及相关审计功能。从管理层面提供互联网的 有效监督,预防、制止数据泄密。满足用户对互联网行为审计备案及 安全保护措施的要求,提供完整的上网记录…...
Apache Maven Assembly 插件简介
Apache Maven Assembly 插件是一个强大的工具,允许您以多种格式(如 ZIP、TAR 和 JAR)创建项目的分发包。 该插件特别适用于将项目与其依赖项、配置文件和其他必要资源一起打包。 通过使用 Maven Assembly 插件,您可以将项目作为…...
ReentrantLock(可重入锁) Semaphore(信号量) CountDownLatch
目录 ReentrantLock(可重入锁) &Semaphore(信号量)&CountDownLatchReentrantLock(可重入锁)既然有了synchronized,为啥还要有ReentrantLock?Semaphore(信号量)如何确保线程安全呢?CountDownLatch ReentrantLock(可重入锁) &Semaphore(信号量…...
计算机网络习题解答--个人笔记(未完)
本篇文章为关于《计算机网络-自顶向下方法第七版》的阅读总结和课后习题解答(未完待续) 第二章: cookie:(这里是比较老版本的HTTP,具体HTTPs是怎么实现的不是很清楚)cookie的原理其实很简单。就是在HTTP消息头上又多…...
java虚拟机——频繁发生Full GC的原因有哪些?如何避免发生Full GC
什么是Full GC Full GC(Full Garbage Collection)是Java垃圾收集过程中的一种形式,它涉及整个堆内存(包括年轻代和老年代)以及方法区的垃圾收集。Full GC是一个相对重量级的操作,因为它需要遍历和回收整个…...
python学习笔记(12)算法(5)迭代与递归
一、迭代 迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段代码,直到这个条件不再满足。 迭代通常用于解决需要逐步推进的计算问题,例如遍历数组、计算阶乘等。迭代…...
从零开始:Linux 环境下的 C/C++ 编译教程
个人主页:chian-ocean 文章专栏 前言: GCC(GNU Compiler Collection)是一个功能强大的编译器集合,支持多种语言,包括 C 和 C。其中 gcc 用于 C 语言编译,g 专用于 C 编译。 Linux GCC or G的安…...
Rust学习(十):计算机科学简述
Rust学习(十):计算机科学简述 在计算机技术这片广袤的领域中,深入理解其内在机制与逻辑需要付出诸多努力。 学习基础知识是构建计算机技术能力大厦的基石,而这一过程往往漫长而艰辛。只有在对基础知识有了扎实的掌握…...
【西瓜书】剪枝与样本值处理——预剪枝、后剪枝、连续值、缺失值
目录 预剪枝 后剪枝 处理连续值 处理缺失值 剪枝(pruning)是决策树学习算法对付“过拟合”的主要手段。 在决策树学习过程中,有时会造成决策树分枝过多,就可能造成过拟合,可通过主动去掉一些分支来降低过离合的风…...
NLP 1、人工智能与NLP简介
人人都不看好你,可偏偏你最争气 —— 24.11.26 一、AI和NLP的基本介绍 1.人工智能发展流程 弱人工智能 ——> 强人工智能 ——> 超人工智能 ① 弱人工智能 人工智能算法只能在限定领域解决特定的问题 eg:特定场景下的文本分类、垂直领域下的对…...
常见线程安全问题之Double Checked Locking
创作内容丰富的干货文章很费心力,感谢点过此文章的读者,点一个关注鼓励一下作者,激励他分享更多的精彩好文,谢谢大家! 双重锁定检查(Double Checked Locking,下称 DCL)是并发下实现懒…...
Redis(非关系型数据库)的作用 详细解读
edis(Remote Dictionary Server)是一个开源的、高性能的、基于内存的数据结构存储系统。它具有极高的读写性能,并且能够支持多种数据结构的存储。Redis 最初的设计目标是作为一个缓存解决方案,但随着其功能的不断扩展,…...
网站制作公司北京网站建设公司哪家好/系统优化的例子
Transformer输入的是token,来自语言序列的启发。卷积神经网络(CNN)是如何进行物种分类的.它实际是直接对特征进行识别,也就是卷积神经网络最基本的作用:提取图像的特征。例如:卷积神经网络判断一只狗的时候,…...
微信网站建设报价表/网络舆情监测
基于对话框的程序。实现界面:打开图片的消息响应函数:void CcountRiceDlg::OnBnClickedOpen(){// TODO: 在此添加控件通知处理程序代码TCHAR szFilters[]_T("BMP Files (*.bmp)|*.png|All Files (*.*)|*.*||");CFileDialog dlg(TRUE,_T("…...
网站制作广/网站备案查询系统
1、获取企业微信信息 1)我的企业 --> 企业信息 --> 企业ID 2)创建一个应用,记录该应用的 AgentId、Secret 2、python代码 #!/usr/bin/env python # -*- coding:utf-8 -*-import json import requestsclass WeChat:def __init__(self):s…...
wordpress安装创建数据库文件/小程序开发工具
大家好呀,打算写一个 Go 语言组件源码分析系列,一是为了能学习下 Go 语言,看下别人是怎么写 Go 的,二是也掌握一个组件。 本次选择了 Sentinel-Go,一是对 Java 版本的 Sentinel 算是有一些了解,也在生产上…...
wordpress视频教程下载地址/app怎么开发出来的
关于cocos2d-x下Lua调用C的文档看了不少,但没有一篇真正把这事给讲明白了,我自己也是个初学者,摸索了半天,总结如下:cocos2d-x下Lua调用C这事之所以看起来这么复杂、网上所有的文档都没讲清楚,是因为存在5个…...
做网站开视频网站/网站技术制作
让我猜猜你心中的牌,先随机生成27张牌,不能重复 列出三列牌,然后记住其中一张,然后点击牌所在的列,多次就可以猜出你想的牌。 如果是9张只要猜2次,如果是27张就是猜3次。 实现方法(27张…...