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...

通过上述代码,我们可以看到,在不同的状态下,相同的操作所执行的具体逻辑是不同的。此外,由于电子开关状态的数量比较有限,因此我们可以轻松地为每个状态实现具体的逻辑。这样,我们就可以将对象的状态和行为分离开来,从而实现了更加灵活、可扩展的代码结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/15313.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flutter开发实战-图片保存到相册

flutter开发实战-图片保存到相册。保存相册使用的是image_gallery_saver插件 一、引入image_gallery_saver插件 在pubspec.yaml中引入插件 # 保存图片到相册image_gallery_saver: ^1.7.1# 权限permission_handler: ^10.0.0二、保存到相册的代码 使用image_gallery_saver将图…

使用pikachu管理工具下的XSS后台进行实战

写在前面的重要提示: Attention:技术没有好坏之分,关键在于使用技术的人或组织。网络安全技术是一把双刃剑 – 作为网络安全人,虽然无法控制头上的帽子是否会变绿,但能控制不让它变黑;无论我们在物质上面对…

redis主从复制哨兵Cluster

目录 前言 一、模式介绍 1.1 主从复制 1.2 哨兵 1.3 集群 二、主从复制 2.1 主从复制的作用 2.2 主从复制流程 2.3 搭建Redis 主从复制 三、Redis 哨兵模式 3.1 哨兵模式原理 3.2 哨兵模式的作用 3.3 哨兵组成结构 3.4 哨兵故障转移机制 3.5 搭建Redis 哨兵模式…

史上最全react面试题

react面试题 react生命周期面试题1.react 生命周期函数2.react生命周期中,最适合与服务端进行数据交互的是哪个函数3.运行阶段生命周期调用顺序4.shouldComponentUpdate 是做什么的,(react 性能优化是哪个周期函数?)5.…

..\obj\project.assets.json”。运行 NuGet 包还原以生成此文件。

问题 有时拉取一个新的项目后出现,如标题中的问题,不管用的是Vs 还是Rider都有可能出现;当使用IDE的自动还原生成相关文件时,没有效果,一般第一次打开项目时IDE是会自动生成的。 解决办法 dotnet msbuild -t:restor…

科技项目验收测试:验证软件产品功能与性能的有效手段

科技项目验收测试是验证软件产品功能与性能的重要手段,在项目开发中起到了至关重要的作用。本文将从产品质量、需求验证、性能测试等方面,探讨科技项目验收测试的有效手段。 1、产品质量保证是验收测试的核心 科技项目验收测试的核心目标是验证软件产品…

开发基于 LoRaWAN 的设备--低功耗设备电池的选项

电池选型简介 在开发物联网 (IoT) 应用无线设备时,选择电池具有挑战性,但对于成功至关重要。使用 LoRaWAN 传感器时,请考虑外形尺寸、容量、峰值电流、自放电、产品寿命和成本,所有这些都会影响您选择的电池。 本文档可帮助您选择最适合您的应用的电池。该文件还: 帮助您确…

xshell连接Windows中通过wsl安装的linux子系统-Ubuntu 22.04

xshell连接Windows中通过wsl安装的linux子系统-Ubuntu 22.04 一、安装linux子系统 1.1、 启动或关闭Windows功能-适用于Linux的Windows子系统 1.2 WSL 官方文档 使用 WSL 在 Windows 上安装 Linux //1-安装 WSL 命令 wsl --install//2-检查正在运行的 WSL 版本:…

关于在VS2017中编译Qt项目遇到的问题

关于在VS2017中编译Qt项目遇到的问题 【QT】VS打开QT项目运行不成功 error MSB6006 “cmd.exe”已退出,代码为 2。如何在VS2017里部署的Qt Designer上编辑槽函数 【QT】VS打开QT项目运行不成功 error MSB6006 “cmd.exe”已退出,代码为 2。 链接 如何在VS2017里部署的Qt Design…

10.python设计模式【代理模式】

内容:为其他对象提供一种代理一控制对这个对象的访问 应用场景: 远程代理: 为远程的对象提供代理虚代理:根据需要创建很大的对象保护代理:控制对原始对象的访问,用于对象有不同访问权限时 UML图 举个例…

VUE,子组件给父组件传递参数,props 自定义属性,ref

<template><div><!-- 子传父 --><!-- 通过父组件给子组件传递函数类型的props实现&#xff1a;子给父传递数据 --><AA :getAAname"getAAname"/><h1>AA&#xff1a;{{aaname}}</h1><!-- 通过父组件给子组件绑定一个自定…

WIZnet W6100-EVB-Pico DHCP 配置教程(三)

前言 在上一章节中我们讲了网络信息配置&#xff0c;那些网络信息的配置都是用户手动的去配置的&#xff0c;为了能跟电脑处于同一网段&#xff0c;且电脑能成功ping通板子&#xff0c;我们不仅要注意子网掩码&#xff0c;对于IP地址主机位和网络位的划分&#xff0c;而且还要注…

selenium定位元素的方法

Selenium可以驱动浏览器完成各种操作&#xff0c;比如模拟点击等。要想操作一个元素&#xff0c;首先应该识别这个元素。人有各种的特征&#xff08;属性&#xff09;&#xff0c;我们可以通过其特征找到人&#xff0c;如通过身份证号、姓名、家庭住址。同理&#xff0c;一个元…

前端框架学习-Vue(三)

目录 初识VueVue模板语法数据绑定el和data的两种写法事件的基本使用$emit在子组件中定义方法&#xff0c;执行父组件的方法 Vue中的事件修饰符&#xff1a;键盘事件计算属性监视属性条件渲染列表渲染表单数据收集过滤器 笔记内容来自&#xff1a;尚硅谷Vue2.0Vue3.0全套教程丨v…

【unity】Pico VR 开发笔记(基础篇)

Pico VR 开发笔记(基础篇) XR Interaction Tooikit 版本 2.3.2 一、环境搭建 其实官方文档已经写的很详细了&#xff0c;这里只是不废话快速搭建&#xff0c;另外有一项官方说明有误的&#xff0c;补充说明一下&#xff0c;在开发工具部分说明 插件安装——安装pico的sdk和XR…

删掉一个元素以后全为 1 的最长子数组

给你一个二进制数组 nums &#xff0c;你需要从中删掉一个元素。 请你在删掉元素的结果数组中&#xff0c;返回最长的且只包含 1 的非空子数组的长度。 如果不存在这样的子数组&#xff0c;请返回 0 。 提示 1&#xff1a; 输入&#xff1a;nums [1,1,0,1] 输出&#xff1…

职责链模式——请求的链式处理

1、简介 1.1、概述 很多情况下&#xff0c;在一个软件系统中可以处理某个请求的对象不止一个。例如SCM系统中的采购单审批&#xff0c;主任、副董事长、董事长和董事会都可以处理采购单&#xff0c;他们可以构成一条处理采购单的链式结构。采购单沿着这条链进行传递&#xff…

编程小白的自学笔记十二(python爬虫入门四Selenium的使用实例二)

系列文章目录 编程小白的自学笔记十一&#xff08;python爬虫入门三Selenium的使用实例详解&#xff09; 编程小白的自学笔记十&#xff08;python爬虫入门二实例代码详解&#xff09; 编程小白的自学笔记九&#xff08;python爬虫入门代码详解&#xff09; 目录 系列文章…

指针应用基础练习

&#xff08;1&#xff09;一级指针&#xff0c;二级指针 void getString(char **p) {*p "hello world"; }int main(void) {char *str NULL;getString(&str);printf("%s\n", str); } 代码分析&#xff1a; 定义了一个char型指针str&#xff0c;…

uni-app踩坑记

打包h5如何配置域名&#xff1a; 在manifest.json中配置域名 配置完成后无论是测试环境还是正式环境都带上/mobile/&#xff0c;否则会报错404 如何引入调试工具erada: 在默认的index.html中直接引入erada&#xff0c;页面样式会整个错乱&#xff0c;解决方案就是引入官方…