Python状态模式介绍、使用
一、Python状态模式介绍
Python状态模式(State Pattern)是一种行为型设计模式,它允许对象在不同的状态下表现不同的行为,从而避免在代码中使用多重条件语句。该模式将状态封装在独立的对象中,并根据当前状态选择不同的行为。
在状态模式中,状态定义为一个独立的类,并在其内部包含其自身不同状态下的操作。其主要功能是将状态和行为分离,提供更高级别的抽象,使代码更易于维护和扩展。
优点:
- 使代码更具有可读性和可维护性;
- 易于扩展和修改状态和行为;
- 将状态转换逻辑放在状态类内部,使其更易于管理。
缺点:
- 可能会增加代码的复杂度;
- 需要使用多个类来实现状态转换,增加了类的数量。
通常用于以下场景:
- 对象的状态转换次数较多;
- 对象的状态远大于其行为;
- 存在状态转换的复杂逻辑。
在使用状态模式时,需要先定义状态类,然后在主对象中引用状态类,从而实现状态转换。在应用程序开发中,状态模式常用于游戏开发、自动售货机和交通信号灯等。
二、状态模式使用
工作原理:
- 主对象持有一个状态类的引用;
- 在状态类实例中定义对象在该状态下的行为;
- 主对象调用状态类的方法,从而实现状态转换。
示例一:实现状态切换功能
为了更加详细地说明Python状态模式的工作原理和使用方法,我们可以使用一个简单的例子进行说明:假设我们有一个程序,可以根据用户输入的不同命令执行不同的操作。我们可以使用状态模式来实现这个程序。
首先,我们定义一个状态类,其中定义了程序在不同状态下的行为:定义了一个抽象的状态类State
,以及三个具体的状态类StartState
、RunningState
、StopState
。在每个具体的状态类中,我们都实现了程序在该状态下的行为。注意到如果该状态下的操作执行成功,则可以返回一个新的状态实例,从而实现状态转换。
接下来,我们定义一个主对象,该对象持有一个状态类的引用,并且可以根据用户输入的命令来执行不同的操作:定义了一个名为Program
的主对象,该对象初始化时持有一个起始状态实例StartState
,并且可以调用该状态实例的execute
方法来执行不同的命令。
最后,我们可以使用以下代码来运行该程序:
# 定义抽象类:1个状态类
class State():def execute(self, command):pass# 定义具体类:3个具体类
class StartState(State):def execute(self, command):if command == "run":print("Program is already running.")else:print("Starting program...")# 这里可以添加具体的启动程序代码return RunningState()return selfclass RunningState(State):def execute(self, command):if command == "run":print("Program is already running.")elif command == "stop":print("Stopping program...")# 这里可以添加具体的停止程序代码return StopState()else:print("Invalid command.")return selfclass StopState(State):def execute(self, command):if command == "run":print("Starting program...")# 这里可以添加具体的启动程序代码return RunningState()elif command == "stop":print("Program is already stopped.")else:print("Invalid command.")return self# 定义主对象
class Program():def __init__(self):self.state = StartState()def execute(self, command):self.state = self.state.execute(command)# 创建实例
program = Program()
program.execute("start")
program.execute("run")
program.execute("stop")
program.execute("stop")
program.execute("invalid comm")
program.execute("run")
运行结果:
Starting program...
Program is already running.
Stopping program...
Program is already stopped.
Invalid command.
Starting program...
在上述代码中,我们首先创建了一个程序实例program
,然后执行了多个命令,包括启动程序、停止程序、执行无效命令等。程序按照不同的状态执行不同的操作,并且根据操作执行结果返回一个新的状态实例,从而实现状态转换。
通过上述例子,我们可以更加详细地了解Python状态模式的工作原理和使用方法。
示例二:实现开关切换功能
Python状态模式通常用于实现那些具有复杂状态的对象,尤其是状态远大于行为的对象。例如,一个电子开关可以处于打开、关闭、断开电路等多种状态之一,每种状态所能执行的操作都是相同的,但是状态的变化却决定了对象的行为。
在这种场景下,我们可以使用Python状态模式来实现对象的不同状态。具体来说,我们可以定义一个抽象状态类和多个具体状态类,每个具体状态类都代表对象的一种状态,并且实现抽象状态类中定义的所有方法。同时,我们还可以定义一个对象类,在其中维护一个当前状态的引用,并对外提供对象的操作接口。每当对象执行某个操作时,对象类就会根据当前状态的不同,将操作委托给具体的状态类进行执行。
下面是一个简单的示例,该示例模拟了一个电子开关的多个状态:
在上面的示例中,我们首先定义了一个Switch
类,该类维护了当前电子开关的状态,并提供了切换状态的方法。然后我们定义了一个抽象状态类State
,该类中定义了开关操作的接口。最后,我们还定义了两个具体状态类OnState
和OffState
,分别代表开启和关闭状态。在具体状态类中,我们实现了开关操作的具体逻辑,并在适当的时候,将状态切换到另一个状态。
可以通过以下方式使用状态模式来模拟电子开关的状态切换:
# 维护开关状态
class Switch():def __init__(self):self.state = OffState()def change_state(self, state):self.state = statedef switch_on(self):self.state.switch_on(self)def switch_off(self):self.state.switch_off(self)# 定义抽象状态类, 定义开关接口
class State():def switch_on(self, switch):passdef switch_off(self, switch):pass# 定义具体类:2个开关状态
class OnState(State):def switch_off(self, switch):print("switching off...")switch.change_state(OffState())class OffState(State):def switch_on(self, switch):print("switching on...")switch.change_state(OnState())# 创建实例
switch = Switch()
switch.switch_on() # 输出:switching on...
switch.switch_on() # 无任何输出
switch.switch_off()# 输出:switching off...
运行结果:
switching on...
switching off...
通过上述代码,我们可以看到,在不同的状态下,相同的操作所执行的具体逻辑是不同的。此外,由于电子开关状态的数量比较有限,因此我们可以轻松地为每个状态实现具体的逻辑。这样,我们就可以将对象的状态和行为分离开来,从而实现了更加灵活、可扩展的代码结构。
相关文章:
Python状态模式介绍、使用
一、Python状态模式介绍 Python状态模式(State Pattern)是一种行为型设计模式,它允许对象在不同的状态下表现不同的行为,从而避免在代码中使用多重条件语句。该模式将状态封装在独立的对象中,并根据当前状态选择不同的…...

Github-Copilot初体验-Pycharm插件的安装与测试
引言: 80%代码秒生成!AI神器Copilot大升级 最近copilot又在众多独角兽公司的合力下,取得了重大升级。GitHub Copilot发布还不到两年, 就已经为100多万的开发者,编写了46%的代码,并提高了55%的编码速度。 …...
Spring AOP API详解
上一章介绍了Spring对AOP的支持,包括AspectJ和基于schema的切面定义。在这一章中,我们将讨论低级别的Spring AOP API。对于普通的应用,我们推荐使用前一章中描述的带有AspectJ pointcuts 的Spring AOP。 6.1. Spring 中的 Pointcut API 这一…...

分治法 Divide and Conquer
1.分治法 分治法(Divide and Conquer)是一种常见的算法设计思想,它将一个大问题分解成若干个子问题,递归地解决每个子问题,最后将子问题的解合并起来得到整个问题的解。分治法通常包含三个步骤: 1. Divid…...
super(Module_ModuleList, self).__init__()的作用是什么?
class Module_ModuleList(nn.Module):def __init__(self):super(Module_ModuleList, self).__init__()self.linears nn.ModuleList([nn.Linear(10, 10)])在这段代码中,super(Module_ModuleList, self).__init__() 的作用是调用父类 nn.Module 的 __init__ 方法&…...

【并发专题】操作系统模型及三级缓存架构
目录 课程内容一、冯诺依曼计算机模型详解1.计算机五大核心组成部分2.CPU内部结构3.CPU缓存结构4.CPU读取存储器数据过程5.CPU为何要有高速缓存 学习总结 课程内容 一、冯诺依曼计算机模型详解 现代计算机模型是基于-冯诺依曼计算机模型 计算机在运行时,先从内存中…...
java基础复习(第二日)
java基础复习(二) 1.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被 synchronized修饰? 都不能。 抽象方法需要子类重写…...

Ansible自动化运维工具
Ansible自动化运维工具 一、ansible介绍二、ansible环境安装部署三、ansible命令行模块1、command模块2、shell模块3、cron模块4、user模块5、group模块6、copy模块7、file模块8、hostname模块9、ping模块10、yum模块11、service/systemd模块12、script模块13、mount模块14、ar…...

LeetCode-116-填充每个节点的下一个右侧节点指针
一:题目描述: 给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下: struct Node {int val;Node *left;Node *right;Node *next; }填充它的每个 next 指针,让这个指…...
前端面试的性能优化部分(3)每篇10题
21.如何优化移动端网页的性能? 优化移动端网页的性能是提升用户体验、降低用户流失的关键。以下是一些优化移动端网页性能的常见方法: 压缩和合并资源: 压缩 CSS、JavaScript 和图片等静态资源,减少文件大小,同时合并…...
如何通过企业工商信息初步判断企业是否靠谱?
银行、投资机构等对企业进行融资、授信、合作时,需要如何评估企业的可靠性。企业工商信息作为企业的基础信息,是初步判断企业是否靠谱的重要依据之一,通过对企业工商信息的综合分析,我们可以了解企业的经营状况、财务实力、法律风…...

ChatGPT+知乎,20分钟超越专业大V的调教方法
AI技术正在迅速发展,渗透到我们的生活中,尤其在内容营销领域。 AI算法帮助我们生成文本、优化搜索引擎排名,提升用户体验等,这些创新正在塑造时代的前进方向,AI也将引领未来十年的变革。对于每个创业者、内容创作者和…...
git branch --show-current 和 git rev-parse --abbrev-ref HEAD 区别
git branch --show-current 和 git rev-parse --abbrev-ref HEAD 区别 git branch --show-current 和 git rev-parse --abbrev-ref HEAD 命令都可以用于获取当前所在的 Git 分支名称。 但是,它们之间有一些不同点: git branch --show-current 命令是 G…...

【TypeScript】接口类型 Interfaces 的使用理解
导语: 什么是 类型接口? 在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement&#x…...

2023-07-31 C语言根据错误号打印详细的错误信息perror(““) 或者strerror(errno)
一、C 语言可以使用perror("perror output"); 或 strerror(errno)打印详细的错误信息。 二、需要的头文件#include <errno.h>。 三、实例测试,这里我让open一个linux 底层杂项设备失败的情况,返回的是一个负数,强制返回-EN…...

JDK17和JDK8完美卸载方法及新版JDK安装教程
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...

FPGA设计时序分析二、建立/恢复时间
目录 一、背景知识 1.1 理想时序模型 1.2 实际时序模型 1.2.1 时钟不确定性 1.2.2 触发器特性 二、时序分析 2.1 时序模型图 2.2 时序定性分析 一、背景知识 之前的章节提到,时钟对于FPGA的重要性不亚于心脏对于人的重要性,所有的逻辑运算都离开…...
oracle建立自动增长字段
oracle数据库与其他的数据库不太一样,比如在mysql里自动增长只要设定“auto_increment”即可。可是在oracle里就没有这种配置了。以oracle11g为例,建立自动增长的字段。操作如下: --创建表 create table USERINFO ( ID NUMBER , …...

【Git】远程仓库的创建、SSH协议克隆、拉取、推送
目录 一、创建远程仓库 二、HTTPS协议克隆仓库 三、SSH协议克隆仓库 四、向远程仓库推送 五、从远程仓库拉取 六、忽略特殊文件 七、配置命令别名 一、创建远程仓库 首先我们可以从GitHub或者Gitee中创建自己的个人仓库 工作台 - Gitee.comhttps://gitee.com/ 二、HTT…...

C#之泛型
目录 一、概述 二、C#中的泛型 继续栈的示例 三、泛型类 (一)声明泛型类 (二)创建构造类型 (三)创建变量和实例 (四)比较泛型和非泛型栈 四、类型参数的约束 (一…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...