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#中的泛型 继续栈的示例 三、泛型类 (一)声明泛型类 (二)创建构造类型 (三)创建变量和实例 (四)比较泛型和非泛型栈 四、类型参数的约束 (一…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
