当前位置: 首页 > news >正文

Python状态模式介绍、使用

一、Python状态模式介绍

Python状态模式(State Pattern)是一种行为型设计模式,它允许对象在不同的状态下表现不同的行为,从而避免在代码中使用多重条件语句。该模式将状态封装在独立的对象中,并根据当前状态选择不同的行为。

在状态模式中,状态定义为一个独立的类,并在其内部包含其自身不同状态下的操作。其主要功能是将状态和行为分离,提供更高级别的抽象,使代码更易于维护和扩展。

优点:

  1. 使代码更具有可读性和可维护性;
  2. 易于扩展和修改状态和行为;
  3. 将状态转换逻辑放在状态类内部,使其更易于管理。

缺点:

  1. 可能会增加代码的复杂度;
  2. 需要使用多个类来实现状态转换,增加了类的数量。

通常用于以下场景:

  1. 对象的状态转换次数较多;
  2. 对象的状态远大于其行为;
  3. 存在状态转换的复杂逻辑。

在使用状态模式时,需要先定义状态类,然后在主对象中引用状态类,从而实现状态转换。在应用程序开发中,状态模式常用于游戏开发、自动售货机和交通信号灯等。

二、状态模式使用

工作原理:

  1. 主对象持有一个状态类的引用;
  2. 在状态类实例中定义对象在该状态下的行为;
  3. 主对象调用状态类的方法,从而实现状态转换。

示例一:实现状态切换功能

为了更加详细地说明Python状态模式的工作原理和使用方法,我们可以使用一个简单的例子进行说明:假设我们有一个程序,可以根据用户输入的不同命令执行不同的操作。我们可以使用状态模式来实现这个程序。

首先,我们定义一个状态类,其中定义了程序在不同状态下的行为:定义了一个抽象的状态类State,以及三个具体的状态类StartStateRunningStateStopState。在每个具体的状态类中,我们都实现了程序在该状态下的行为。注意到如果该状态下的操作执行成功,则可以返回一个新的状态实例,从而实现状态转换。

接下来,我们定义一个主对象,该对象持有一个状态类的引用,并且可以根据用户输入的命令来执行不同的操作:定义了一个名为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,该类中定义了开关操作的接口。最后,我们还定义了两个具体状态类OnStateOffState,分别代表开启和关闭状态。在具体状态类中,我们实现了开关操作的具体逻辑,并在适当的时候,将状态切换到另一个状态。

可以通过以下方式使用状态模式来模拟电子开关的状态切换:

# 维护开关状态
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>。 三、实例测试&#xff0c;这里我让open一个linux 底层杂项设备失败的情况&#xff0c;返回的是一个负数&#xff0c;强制返回-EN…...

JDK17和JDK8完美卸载方法及新版JDK安装教程

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

FPGA设计时序分析二、建立/恢复时间

目录 一、背景知识 1.1 理想时序模型 1.2 实际时序模型 1.2.1 时钟不确定性 1.2.2 触发器特性 二、时序分析 2.1 时序模型图 ​2.2 时序定性分析 一、背景知识 之前的章节提到&#xff0c;时钟对于FPGA的重要性不亚于心脏对于人的重要性&#xff0c;所有的逻辑运算都离开…...

oracle建立自动增长字段

oracle数据库与其他的数据库不太一样&#xff0c;比如在mysql里自动增长只要设定“auto_increment”即可。可是在oracle里就没有这种配置了。以oracle11g为例&#xff0c;建立自动增长的字段。操作如下&#xff1a; --创建表 create table USERINFO ( ID NUMBER , …...

【Git】远程仓库的创建、SSH协议克隆、拉取、推送

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

C#之泛型

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

Scrum敏捷开发管理流程+scrum工具免费

Leangoo领歌它覆盖了敏捷项目研发全流程&#xff0c;包括小型团队Scrum敏捷开发&#xff0c;规模化敏捷SAFe&#xff0c;Scrum of Scrums大规模敏捷。它提供了灵活的敏捷模板和极致的协作体验&#xff0c;可以让团队快速上手&#xff0c;快速落地Scrum敏捷开发管理。 首先建立产…...

【操作系统基础】Linux 中 /var/log/ 文件夹下通常有哪一些文件?分别的作用是什么?

在Linux系统中&#xff0c;/var/log/ 文件夹通常包含了系统日志文件&#xff0c;这些文件记录了系统的各种活动和事件&#xff0c;以便管理员进行故障排除和监控。 以下是/var/log/ 文件夹中常见的一些文件及其含义&#xff1a; auth.log&#xff1a;记录系统认证和授权相关的…...

【构造】CF1758 C

Problem - 1758C - Codeforces 题意&#xff1a; 思路&#xff1a; 思路&#xff1a; #include <bits/stdc.h>#define int long longusing namespace std;const int mxn2e510; const int mxe2e510;int N,x; int ans[mxn];void solve(){cin>>N>>x;if(N%x!0)…...

【etcd】docker 启动单点 etcd

etcd: v3.5.9 etcd-browser: rustyx/etcdv3-browser:latest 本文档主要描述用 docker 部署单点的 etcd&#xff0c; 用 etcd-browser 来查看注册到 etcd 的 key 默认配置启动 docker run -d --name ai-etcd --networkhost --restart always \-v $PWD/etcd.conf.yml:/opt/bitn…...

【单链表OJ题:反转链表】

题目来源 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* reverseList(struct ListNode* head){struct ListNode* current head;struct ListNode* newnode NULL;while(current!NULL){struc…...

Unity UGUI的LayoutRebuilder的介绍及使用

Unity UGUI的LayoutRebuilder的介绍及使用 1. 什么是LayoutRebuilder&#xff1f; LayoutRebuilder是Unity UGUI中的一个组件&#xff0c;用于自动重建布局。它可以根据UI元素的变化&#xff0c;自动调整其子元素的位置和大小&#xff0c;以保持布局的一致性。 2. LayoutReb…...

深刻理解python特性-列表推导式和生成器表达式

哈喽大家好&#xff0c;今天给大家介绍两个Python中特性-列表推导式和生成器表达式 今天我想向你介绍python语言的两个非常有用的特性&#xff1a;列表推导式和生成器表达式。这两个特性都可以让你用一行简洁的代码来创建一个序列&#xff0c;而不需要写循环或者函数。但是它们…...

Sentinel dashboard的使用;Nacos保存Sentinel限流规则

Sentinel dashboard的使用 往期文章 Nacos环境搭建Nacos注册中心的使用Nacos配置中心的使用Sentinel 容灾中心的使用 参考文档 Sentinel alibaba/spring-cloud-alibaba Wiki GitHub 限流结果 下载sentinel-dashboard github地址&#xff1a;Sentinel/sentinel-dashboar…...

vue学习之插值表达式{{}}与显示数据(v-text和v-html)

1. 记得导入 <!-- 在线导入 --> <!-- 开发环境版本&#xff0c;包含了用帮助的命令行警告 --> <script src"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 生产环境版本&#xff0c;优化了尺寸和速度 --> <scri…...

2,认识N(logN)的排序【p3】

认识N( logN} 的排序 2.1归并排序2.1.1代码实现归并排序2.1.1.1自己c实现归并排序2.1.1.2gptc实现归并排序2.1.1.3总结2.1.1.4比较行为 2.1.2归并排序使用master公式2.1.3归并排序的扩展2.1.3.1小和问题2.1.3.2逆序对问题 2.2快排、荷兰国旗问题2.2.1问题一2.2.2问题二(荷兰国旗…...