C# 设计模式之状态模式

devtools/2024/9/22 14:40:33/

总目录


前言

状态模式在我们的现实生活中也有类似的例子,例如:在我们上网购买商品的过程中,就可以查看订单的实时状态。对于商家来说,订单的状态不同,也会允许客户有不同的动作要求,比如:订单在已经处于发货状态,此订单是不能退货的。如果订单在备货阶段,客户是可以换货或者退货的。如果我们的订单已经发货了,您就等着接收货物吧,如果货物有质量问题,可以拒签,或者顺利完成交易。


1 基础介绍

  1. 定义:允许一个对象在其内部状态改变时自动改变其行为,对象看起来就像是改变了它的类。
  2. 每个对象都有其对应的状态,而每个状态又对应一些相应的行为,如果某个对象有多个状态时,那么就会对应很多的行为。那么对这些状态的判断和根据状态完成的行为,就会导致多重条件语句,并且如果添加一种新的状态时,需要更改之前现有的代码。这样的设计显然违背了开闭原则。状态模式正是用来解决这样的问题的。状态模式将每种状态对应的行为抽象出来成为单独新的对象,这样状态的变化不再依赖于对象内部的行为。
  3. 状态模式有以下角色:
    • 环境角色(Context):也称上下文,定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
    • 抽象状态角色(State):定义一个接口,用以封装环境对象的一个特定的状态所对应的行为。
    • 具体状态角色(ConcreteState):每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。

状态模式结构中需要理解环境类与抽象状态类的作用:

  • 环境类实际上就是拥有状态的对象,环境类有时候可以充当状态管理器(State Manager)的角色,可以在环境类中对状态进行切换操作。
  • 抽象状态类可以是抽象类,也可以是接口,不同状态类就是继承这个父类的不同子类,状态类的产生是由于环境类存在多个状态,同时还满足两个条件:这些状态经常需要切换,在不同的状态下对象的行为不同。因此可以将不同对象下的行为单独提取出来封装在具体的状态类中,使得环境类对象在其内部状态改变时可以改变它的行为,对象看起来似乎修改了它的类,而实际上是由于切换到不同的具体状态类实现的。由于环境类可以设置为任一具体状态类,因此它针对抽象状态类进行编程,在程序运行时可以将任一具体状态类的对象设置到环境类中,从而使得环境类可以改变内部状态,并且改变行为。

2 使用场景

  • 对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为。

  • 代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,使客户类与类库之间的耦合增强。在这些条件语句中包含了对象的行为,而且这些条件对应于对象的各种状态

3 实现方式

在这里以酒店房间预定为案例说明:
在这里插入图片描述
状态变迁:

然后是3个状态类,这个三个状态分别对应:空闲、预订、入住。其中空闲可以完成预订和入住两个动作,预订可以完成入住和退订两个动作,入住可以退房。

状态接口

public interface IState{/// <summary>/// 预定房间/// </summary>void bookRoom();/// <summary>/// 退订房间/// </summary>void UnSubscribeRoom();/// <summary>/// 入住/// </summary>void CheckInRoom();/// <summary>/// 退房/// </summary>void CheckOutRoom();}

房间类(包含状态的环境角色)

	public class Room{/// <summary>/// 房间的当前状态/// </summary>private IState _state;public IState State{get { return _state; }set { _state = value; }}/// <summary>/// 房间的三个状态/// </summary>private IState _freeTimeState; //空闲状态private IState _checkInState;  //入住状态private IState _bookedState;   //预定状态/// <summary>/// 空闲状态/// </summary>public IState FreeTimeState{get { return _freeTimeState; }set { _freeTimeState = value; }}/// <summary>/// 入住状态/// </summary>public IState CheckInState{get { return _checkInState; }set { _checkInState = value; }}/// <summary>/// 预定状态/// </summary>public IState BookedState{get { return _bookedState; }set { _bookedState = value; }}public Room(){this._freeTimeState = new FreeTimeState(this);this._checkInState = new CheckInState(this);this._bookedState = new BookedState(this);this._state = this._freeTimeState;}/// <summary>/// 预定房间/// </summary>public void bookRoom(){this._state.bookRoom();}/// <summary>/// 退订房间/// </summary>public void UnSubscribeRoom(){this._state.UnSubscribeRoom();}/// <summary>/// 入住/// </summary>public void CheckInRoom(){this._state.CheckInRoom();}/// <summary>/// 退房/// </summary>public void CheckOutRoom(){this._state.CheckOutRoom();}public string getRoomState(){return "该房间的状态是:" + this.State.GetType().ToString();}}

空闲状态

	public class FreeTimeState:IState{private Room _room;public FreeTimeState(){ }public FreeTimeState(Room room){this._room= room;}public void bookRoom(){//设置状态为已经预定状态this._room.State = this._room.BookedState;Console.WriteLine("您已经成功预定了...");}public void UnSubscribeRoom(){//暂不操作}public void CheckInRoom(){this._room.State = this._room.CheckInState;Console.WriteLine("您已经成功入住...");}public void CheckOutRoom(){//暂不操作}}

预定状态

	public class BookedState:IState{private Room _room;public BookedState(){ }public BookedState(Room room){this._room= room;}public void bookRoom(){Console.WriteLine("该房间已经预定了...");}public void UnSubscribeRoom(){this._room.State = this._room.FreeTimeState;Console.WriteLine("退订成功,欢迎下次光临...。");}public void CheckInRoom(){this._room.State = this._room.CheckInState;Console.WriteLine("入住成功...");}public void CheckOutRoom(){//暂不操作}}

入住状态

	public class CheckInState:IState{private Room _room;public CheckInState(){ }public CheckInState(Room room){this._room= room;}public void bookRoom(){Console.WriteLine("该房间已经入住...");}public void UnSubscribeRoom(){//暂不操作}public void CheckInRoom(){Console.WriteLine("该房间已经入住...");}public void CheckOutRoom(){this._room.State = this._room.FreeTimeState;Console.WriteLine("退房成功...");}}

客户端调用:

		static void Main(string[] args){//创建俩间房子Room[] rooms = new Room[2];//初始化for (int i = 0; i < rooms.Length; i++){rooms[i] = new Room();}//第一间房子rooms[0].bookRoom(); //预定rooms[0].CheckInRoom();//入住rooms[0].bookRoom(); //再次预定Console.WriteLine(rooms[0].State);Console.WriteLine("-------------------");//第二间房子rooms[1].CheckInRoom(); //入住rooms[1].bookRoom(); //预定rooms[1].CheckInRoom(); //入住rooms[1].bookRoom();//再次预定Console.WriteLine(rooms[1].State);Console.WriteLine("-------------------");Console.Read();}

4 优缺点分析

优点:

  • 将状态判断逻辑每个状态类里面,可以简化判断的逻辑。
  • 当有新的状态出现时,可以通过添加新的状态类来进行扩展,扩展性好。

缺点:

  • 如果状态过多的话,会导致有非常多的状态类,加大了开销。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

结语

希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:
C#设计模式之十八状态模式(State Pattern)【行为型】
C#设计模式(19)——状态者模式(State Pattern)
使用 C# 实现23种常见的设计模式
C#设计模式状态模式


http://www.ppmy.cn/devtools/113854.html

相关文章

pdf文件转图片,base64或保存到本地

pdf转图片&#xff0c;需要引入pdfbox依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.27</version> </dependency>RequestMapping("pdfToImg") public void …

一天认识一个硬件之显示器

今天还是来给大家分享一个日常都能用到的&#xff0c;显示器&#xff0c;也叫显示屏&#xff0c;屏幕&#xff0c;怎么叫的都有&#xff0c; 先来分享一下什么是显示器&#xff0c;显示器是一种将电子文件通过特定的传输设备显示到屏幕上的显示工具&#xff0c;它的作用是将计…

【C++】多态的认识和理解

个人主页 文章目录 ⭐一、多态的概念&#x1f384;二、多态的定义及实现1.多态的构成2.实现多态的条件3.虚函数的概念4.虚函数的重写和覆盖5.析构函数的重写6.协变7.override和 final关键字8.重载、重写/覆盖、隐藏这三者的区别 &#x1f3e0;三、纯虚函数和抽象类的关系&#…

redis的一主二从三哨兵配置

redis安装脚本 参考了&#xff1a;https://yunweiba.com/163.html https://download.redis.io/releases/ 在上面链接选择合适的版本 wget -P "/opt" https://download.redis.io/releases/redis-7.0.0.tar.gz安装脚本如下&#xff1a; #!/bin/bash # 安装redis&a…

音视频直播应用场景探讨之RTMP推流还是GB28181接入?

技术背景 好多开发者跟我们沟通音视频解决方案的时候&#xff0c;不清楚什么时候用RTMP推送模块&#xff0c;什么时候用GB28181设备接入模块&#xff0c;也不清楚二者差异化。实际上&#xff0c;RTMP推流和GB28181接入模块&#xff0c;在很多方面存在差异&#xff0c;如应用领…

实时系统资源监测:AutoPowerOptionsOK确保电脑性能与节能兼备

科技赋予生活翅膀&#xff0c;让我们在快节奏中翱翔&#xff0c;协调工作与梦想&#xff0c;让每一个梦想都有机会照进现实&#xff0c;绽放光彩——科技的进步不仅推动了社会的发展&#xff0c;也极大地改善了人们的日常生活。在众多科技成果中&#xff0c;电脑作为信息处理的…

基于web的 BBS论坛管理系统设计与实现

博主介绍&#xff1a;专注于Java .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的可以…

老旧电力系统安全隐患增加 该如何预防电气线路老化等因素引发的电气火灾呢?

为应对我国电气火灾事故频发的挑战&#xff0c;安科瑞电气股份有限公司开发了AcrelCloud-6000安全用电管理云平台。这一平台依托移动互联网和云计算技术&#xff0c;结合物联网传感器&#xff0c;将办公楼、学校、医院、工厂、体育场馆、宾馆及福利院等人员密集场所的电气安全数…