设计模式行为型-状态模式

文章目录

  • 简介
  • 状态模式基础
    • 定义状态接口或抽象类
      • 实现具体状态类
  • 上下文类与状态转换
    • 上下文类的定义和作用
    • 状态转换及触发条件
  • 状态模式的优势与适用性
    • 优点一:可维护的代码
    • 优点二:清晰的状态管理
    • 适用场景一:对象拥有多个状态
    • 适用场景二:状态转换频繁且复杂
  • 具体业务场景应用:电商订单状态切换
  • 状态模式与其他设计模式的结合
    • 策略模式与状态模式的对比与联系
    • 工厂模式与状态模式的结合实践
  • 总结

简介

  • 状态模式是一种行为型设计模式,用于处理对象在不同状态下的行为变化。它将对象的行为封装在不同状态类中,通过状态的切换实现不同行为的触发。
  • 本文将介绍状态模式的基本概念、应用场景以及优势与适用性。
    在这里插入图片描述

状态模式基础

定义状态接口或抽象类

public abstract class State{public abstract void WriteProgram(Work w);}

实现具体状态类

    //上午工作状态public class ForenoonState : State{public override void WriteProgram(Work w){
//这里的判断就是决定要用那种行为展现出来,如果 不符合当前状态,那么就去到已经设置好的下一个具体状态类中进行相同的操作。if (w.hour < 12){Console.WriteLine("当前时间:{0}点 上午工作,精神百倍",w.Hour);}else{w.SetState(new NoonState());w.WriteProgram();}}}//中午工作状态public class NoonState : State{public override void WriteProgram(Work w){if (w.hour < 13){Console.WriteLine("当前时间:{0}点 饿了,想吃饭;犯困,想睡觉。", w.Hour);}else{w.SetState(new AfternoonState()); w.WriteProgram();}}}//下午工作状态public class AfternoonState : State{public override void WriteProgram(Work w){if (w.hour < 17){Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力", w.Hour);}else{w.SetState(new EveningState()); w.WriteProgram();}}}//晚上工作状态public class EveningState : State{public override void WriteProgram(Work w){if (w.finish ){w.SetState(new RestState());w.WriteProgram();//完成任务就转成下班状态}else{if (w.hour <21){Console.WriteLine("当前时间:{0}点 加班了,加班人累啊", w.Hour);}else {w.SetState(new SleepingState()); w.WriteProgram();//超过21点,转入睡眠状态}}}}//睡眠状态public class SleepingState:State{public override void WriteProgram(Work w){Console.WriteLine("当前时间:{0}点 不行了,睡着了", w.Hour);}}//下班休息状态public class RestState : State{public override void WriteProgram(Work w){Console.WriteLine("当前时间:{0}点 不行了,睡着了", w.Hour);}}

具体工作类:

    public class Work{public State current;public Work(){current = new ForenoonState();	//初始化为上午9点开始上班}public double hour;//小时钟,状态转换的依据public bool finish = false;//完成任务属性,是否能下班的依据//这个方法主要就是把具体的状态类给进来,然后让下面的方法去使用public void SetState(State s)	//得到状态{current = s;}
//下面这个方法从始至终都没有发生改变,改变是其内部具体的展现值。public void WriteProgram() {current.WriteProgram(this);}}

上下文类与状态转换

上下文类的定义和作用

  • 上下文类包含状态对象的引用,并将具体行为委托给当前状态对象执行。
  • 示例代码:
// 上下文类
public class Context {private State currentState;public void setCurrentState(State state) {this.currentState = state;}public void request() {// 委托当前状态对象执行行为currentState.handle();}
}

状态转换及触发条件

  • 状态转换指从一个状态切换到另一个状态的过程。
  • 触发条件是使状态转换发生的条件。
  • 示例代码:
// 具体状态类A
public class ConcreteStateA implements State {// ...@Overridepublic void handle() {// 具体状态A的行为逻辑// 状态转换及触发条件if (/*触发条件*/) {context.setCurrentState(new ConcreteStateB());}}
}

状态模式的优势与适用性

优点一:可维护的代码

  • 状态模式将每个状态的行为逻辑封装在独立的状态类中,易于理解和维护。

优点二:清晰的状态管理

  • 状态模式通过上下文类进行状态转换和行为委托,使状态管理更加清晰明确。

适用场景一:对象拥有多个状态

  • 当对象具有多个状态且不同状态下表现出不同行为时,可以使用状态模式进行状态管理和行为切换。

适用场景二:状态转换频繁且复杂

  • 当状态转换频繁且存在复杂的触发条件时,状态模式能够提供一种结构化的方式来管理状态转换。

具体业务场景应用:电商订单状态切换


为了演示订单状态管理的状态模式业务代码,我将使用Java语言来实现。以下是一个简单的示例:

首先,我们定义订单状态接口 OrderState,其中包含了处理订单状态的方法 handle()

// 订单状态接口
public interface OrderState {void handle();
}

然后,我们创建具体的订单状态类,包括待支付状态、已支付状态、待发货状态和已发货状态。每个状态类实现了订单状态接口,并根据相应的状态实现了自己的行为逻辑。

// 待支付状态类
public class PendingPaymentState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:待支付");// 处理待支付状态的逻辑}
}// 已支付状态类
public class PaidState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:已支付");// 处理已支付状态的逻辑}
}// 待发货状态类
public class ToBeShippedState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:待发货");// 处理待发货状态的逻辑}
}// 已发货状态类
public class ShippedState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:已发货");// 处理已发货状态的逻辑}
}

接下来,我们创建订单类 Order,它包含了当前订单状态和一些操作方法。

// 订单类
public class Order {private OrderState currentState; // 当前订单状态public Order() {currentState = new PendingPaymentState(); // 默认初始状态为待支付}public void setCurrentState(OrderState state) {currentState = state;}public void request() {currentState.handle();}
}

最后,我们可以进行测试,模拟订单在不同状态下的行为变化:

public class Main {public static void main(String[] args) {Order order = new Order(); // 创建订单// 待支付状态order.request();// 支付订单,状态转换为已支付order.setCurrentState(new PaidState());order.request();// 发货,状态转换为待发货order.setCurrentState(new ToBeShippedState());order.request();// 完成发货,状态转换为已发货order.setCurrentState(new ShippedState());order.request();}
}

运行以上代码,将得到如下输出:
在这里插入图片描述

以上示例演示了订单状态管理的状态模式业务代码。通过状态模式,我们可以根据订单状态的变化触发不同的行为逻辑,并且可以方便地添加新的订单状态,以满足业务需求。

状态模式与其他设计模式的结合

策略模式与状态模式的对比与联系

策略模式和状态模式都属于行为型设计模式,它们都关注对象在不同的情境下具有不同的行为。虽然它们有相似之处,但在设计意图、应用场景和实现方式上存在一些差异。

下面是策略模式和状态模式的对比与联系:

对比:

  1. 设计意图:策略模式旨在通过定义一组算法或策略,并将其封装成独立的对象,使得这些算法可以互换使用。状态模式旨在让一个对象在其内部状态改变时改变其行为,从而实现状态之间的转换。

  2. 关注点:策略模式主要关注算法的选择和封装,使得具体的策略可以独立于客户端进行变化。状态模式主要关注对象的状态的管理和转换,以及不同状态下的行为执行。

  3. 对象角色:策略模式通常包含一个上下文类(Context)和一组策略类(Strategies),客户端与上下文类进行交互。状态模式通常包含一个上下文类(Context)和一组状态类(States),客户端与上下文类进行交互。

联系:

  1. 行为的封装:策略模式和状态模式都将行为封装到独立的对象中,使得行为可以被动态地变化。

  2. 对象之间的互动:策略模式和状态模式都需要一个上下文类(Context)来与策略对象或状态对象进行交互,并将具体的行为委托给策略对象或状态对象来执行。

  3. 可扩展性:策略模式和状态模式都具有较好的可扩展性。在策略模式中,可以方便地新增、修改或切换不同的策略对象。在状态模式中,可以方便地新增、修改或切换不同的状态对象。

总的来说,策略模式和状态模式都是强调对象行为的灵活性和可扩展性的设计模式。它们的主要区别在于策略模式关注算法的选择和封装,而状态模式关注对象状态的管理和转换。根据具体的需求,选择适合的模式来提高代码的可维护性和可扩展性。

工厂模式与状态模式的结合实践

  • 结合工厂模式可以实现状态类的动态创建和切换,增强了状态模式的灵活性和可扩展性。
    结合工厂模式可以实现状态类的动态创建和切换,从而增强了状态模式的灵活性和可扩展性。工厂模式可以将状态对象的创建和状态转换逻辑与客户端代码分离,使得系统更加可维护和可扩展。

下面是一个示例,演示了如何结合工厂模式和状态模式来管理订单的状态:

首先,定义订单状态接口 OrderState 和具体的订单状态类,与之前的示例相同。

// 订单状态接口
public interface OrderState {void handle();
}// 待支付状态类
public class PendingPaymentState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:待支付");// 处理待支付状态的逻辑}
}// 已支付状态类
public class PaidState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:已支付");// 处理已支付状态的逻辑}
}// 待发货状态类
public class ToBeShippedState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:待发货");// 处理待发货状态的逻辑}
}// 已发货状态类
public class ShippedState implements OrderState {@Overridepublic void handle() {System.out.println("当前订单状态:已发货");// 处理已发货状态的逻辑}
}

然后,创建一个工厂类 OrderStateFactory,用于动态创建订单状态对象。
在严格意义上这个工厂是一个不支持扩充的,但是在这里仅作为一个示例,如果想要真正达到动态创建还是需要用到工厂方法,这里只能算是一个简单工厂。

// 订单状态工厂类  
public class OrderStateFactory {public static OrderState createOrderState(String stateName) {switch (stateName.toLowerCase()) {case "pendingpayment":return new PendingPaymentState();case "paid":return new PaidState();case "tobeshipped":return new ToBeShippedState();case "shipped":return new ShippedState();default:throw new IllegalArgumentException("Invalid state name");}}
}

接下来,我们可以使用上述的状态类和工厂类进行订单状态切换的实践:

public class Main {public static void main(String[] args) {Order order = new Order(); // 创建订单// 设置待支付状态order.setCurrentState(OrderStateFactory.createOrderState("PendingPayment"));order.request();// 支付订单,切换到已支付状态order.setCurrentState(OrderStateFactory.createOrderState("Paid"));order.request();// 发货,切换到待发货状态order.setCurrentState(OrderStateFactory.createOrderState("ToBeShipped"));order.request();// 完成发货,切换到已发货状态order.setCurrentState(OrderStateFactory.createOrderState("Shipped"));order.request();}
}

通过工厂模式,我们可以根据状态名称动态地创建不同的订单状态对象,并将其设置为上下文类的当前状态。这样,如果要新增或修改订单状态,只需要修改工厂类的代码,而不需要修改客户端的代码。这增强了状态模式的灵活性和可扩展性。

总结

  • 状态模式是一种有助于管理对象不同状态下行为变化的设计模式。通过将状态和行为封装在不同状态类中,状态模式提供了一种结构化的方式来处理状态转换和行为委托。它适用于对象拥有多个状态且状态转换复杂的场景,并与其他设计模式如策略模式、工厂模式等相结合能够进一步扩展其功能和灵活性。

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

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

相关文章

【Unity】常见的角色移动旋转

在Unity 3D游戏引擎中&#xff0c;可以使用不同的方式对物体进行旋转。以下是几种常见的旋转方式&#xff1a; 欧拉角&#xff08;Euler Angles&#xff09;&#xff1a;欧拉角是一种常用的旋转表示方法&#xff0c;通过绕物体的 X、Y 和 Z 轴的旋转角度来描述物体的旋转。在Un…

区块链技术与应用 - 学习笔记1【引言】

大家好&#xff0c;我是比特桃。本系列主要将我之前学习区块链技术时所做的笔记&#xff0c;进行统一的优化及整合。其中大量笔记源于视频课程&#xff1a;北京大学肖臻老师《区块链技术与应用》公开课。肖老师的课让我找回了求知若渴般的感觉&#xff0c;非常享受学习这门课的…

内存管理方式

内存管理 一、C/C内存分布1、内存空间的介绍2、示例题目3、示例题目图解 二、C语言动态内存管理方式1、代码2、介绍 三、C内存管理方式1、概念2、代码3、代码所代表的意义 四、new和delete操作自定义类型1、代码2、运行结果3、特点 五、operator new与operator delete函数1、概…

Go的数据结构-hashmap

开放寻址法和拉链法 runtime.hamp bucket的数据结构 bucket的指针指向这里 map初始化&#xff1a;make 和字面量 make初始化 新建一个hamp结尾体&#xff0c;计算大B&#xff0c;创建一个桶数组 字面量初始化 map的并发解决 sync.map

无涯教程-JavaScript - QUARTILE函数

QUARTILE函数取代了Excel 2010中的QUARTILE.INC函数。 描述 该函数返回数据集的四分位数。四分位数通常用于销售和调查数据中,以将人群分为几类。 语法 QUARTILE (array,quart)争论 Argument描述Required/OptionalArrayThe array or cell range of numeric values for whi…

怎么提取视频中的音乐保存到本地?其实方法很简单

当你想要使用视频中的音乐时&#xff0c;你可以考虑将它从视频中提取出来。这可以用于制作音频样本集&#xff0c;制作铃声或其他音频素材&#xff0c;或者向其他人展示视频的音乐部分而无需显示视频本身。如果你是一位音乐制作人员&#xff0c;你可能会需要一些特定类型的音效…

CP Autosar-Ethernet配置

文章目录 前言一、Eth层级结构介绍二、Autosar实践2.1 ETH Driver2.2 Eth InterfaceEth Interface Autosar配置2.3 TcpIp模块Eth TcpIp Autosar配置2.4 SoAdEth SoAd配置前言 因汽车E/E架构和功能的复杂度提升而带来的对车辆数据传输带宽提高和通讯方式改变(基于服务的通讯-S…

JavaScript(函数,作用域和闭包)

目录 一&#xff0c;什么是函数1.1&#xff0c;常用系统函数1.2&#xff0c;函数声明 1.3&#xff0c;函数表达式二&#xff0c;预解析2.1&#xff0c;函数自调用 2.2&#xff0c;回调函数三&#xff0c;变量的作用域3.1&#xff0c;隐式全局变量 四&#xff0c;作用域与块级作…

Seaborn绘制热力图的子图

Seaborn绘制热力图的子图 提示&#xff1a;如何绘制三张子图 绘制的时候&#xff0c;会出现如下问题 &#xff08;1&#xff09;如何绘制1*3的子图 &#xff08;2&#xff09;三个显示条&#xff0c;如何只显示最后一个 提示&#xff1a;下面就展示详细步骤 Seaborn绘制热力…

vue 根据数值判断颜色

1.首先style样式给两种颜色 用:class 三元运算符判断出一种颜色 第一步&#xff1a;在style里边设置两种颜色 .green{color: green; } .orange{color: orangered; }在取数据的标签 里边 判断一种颜色 :class"item.quote.current >0 ?orange: green"<van-gri…

单片机-控制按键点亮LED灯

1、按键电路图 定义四个按键引脚 1、按键按下 为 输入为低电平 2、按键不按下 IO有上拉电阻&#xff0c;为高电平 // 定义 按键的 管教 sbit KEY1 P3^1; sbit KEY2 P3^0; sbit KEY3 P3^2; sbit KEY4 P3^3; 2、LED灯电路图 LED 输出高电平为亮 // 定义LED灯 管教 sbit LED1…

pycharm 打开Terminal时报错activate.ps1,因为在此系统上禁止运行脚本,并因此无法进入虚拟环境

pycharm 打开Terminal时报错activate.ps1&#xff0c;因为在此系统上禁止运行脚本&#xff0c;并因此无法进入虚拟环境 如下图所示&#xff1a; 网上说可以set_restrictFalse什么的&#xff0c;虽然也可但可能会降低电脑安全性&#xff0c;可以将下面的终端改为cmd.exe即可

使用candump+grep查看CAN报文

在Linux系统中观察看CAN报文&#xff0c;我们一般使用candump&#xff0c;但是有时候会发现总线上CAN报文太多&#xff0c;例如开启了好几个PDO&#xff0c;这就导致想看的报文被夹杂到报文的海洋里&#xff0c;然后再去找&#xff0c;非常麻烦。 candump也提供了只观察某个报…

ImageSharp.Web实战:轻松搭建高效图片服务

很多情况下&#xff0c;在开发如PC、H5、小程序等综合平台的时候&#xff0c;图片的展示是个比较头疼的问题。尤其是有会员功能&#xff0c;会员可以上传图片的平台&#xff0c;更是一件麻烦事。 平台展示图片的地方&#xff0c;尺寸是定义好的。但用户不配合&#xff0c;上传的…

开发总结:webpack

webpack官网webpack | webpack 中文文档 | webpack 中文网 一、什么是webpack webpack 可以看做是模块打包机&#xff0c;它所做的事情是&#xff1a;分析你的项目结构&#xff0c;找到JavaScript 模块以及其它的一些浏览器不能直接运行的拓展语言&#xff08;Scss&#xff0…

Segment Routing原理

以上内容均属原创&#xff0c;如有不详或错误&#xff0c;敬请指出。本文作者&#xff1a; 坏坏 本文链接&#xff1a; http://t.csdn.cn/2fUE5 版权声明&#xff1a; 本博客所有文章除特别声明外&#xff0c;如需转载&#xff0c;请联系作者注明出处并附带本文链接&#xf…

处理时延降低24倍,联通云粒数据引擎优化实践

*作者&#xff1a;郑扬勇&#xff0c;云粒星河数据中台产品负责人 云粒智慧科技有限公司成立于 2018 年 6 月&#xff0c;是中国联通集团混改以来成立的首家合资公司&#xff0c;是中国智慧城市数智化建设者。一直以来&#xff0c;云粒智慧以数字化、智能化、集约化产品为核心&…

CS144(2023 Spring)Lab 0:networking warmup(环境搭建 webget bytestream)

文章目录 前言其他笔记相关链接 1. Set up GNU/Linux on your computer2. Networking by hand3. Writing a network program using an OS stream socket3.1 Linux配置3.2 C规范3.3 Writing webget3.3.1 实现3.3.2 测试 4. An in-memory reliable byte stream4.1 思路分析4.2 代…

HTTPS安全通信和SSL Pinning

随着互联网的迅速发展&#xff0c;网络通信安全问题日益凸显。在这一背景下&#xff0c;HTTPS作为一种加密通信协议得到了广泛应用&#xff0c;以保障用户的数据隐私和信息安全。本文将介绍HTTPS的基本原理、发展历程&#xff0c;以及与之相关的中间人攻击和防护方法。 1. HTT…

Lesson4-1:OpenCV图像特征提取与描述---角点特征

学习目标 理解图像的特征知道图像的角点 1 图像的特征 大多数人都玩过拼图游戏。首先拿到完整图像的碎片&#xff0c;然后把这些碎片以正确的方式排列起来从而重建这幅图像。如果把拼图游戏的原理写成计算机程序&#xff0c;那计算机就也会玩拼图游戏了。 在拼图时&#xff…