状态模式(State Pattern)

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/425 访问。

状态模式属于行为型模式,它允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

角色:

1、抽象状态(State)

状态模式的核心基类,它表示某种对象的不同状态;

2、具体状态(Concrete State)

实现抽象状态的具体状态类;

3、环境类(Context)

拥有状态的具体对象,该对象会根据内部不同的对象有不同的行为。

示例:

命名空间StatePattern中包含抽象状态类State,代表水的3种状态,0度及以下时为SolidState固体状态,0到100度为LiquidState液体状态,100度及以上时为GasState气体状态,并且不同的状态可以改变水类Water中喝水Drink方法的行为。本案例尝试以水的3种不同状态来向大家阐述状态模式在实际开发中的应用。

namespace StatePattern
public class Water {public State State { get; set; }public double Temperature { get; set; } = 0;public Water() {State = new SolidState();State.Water = this;}public Water Increase(int value) {State.Increase(value);return this;}public Water Reduce(int value) {State.Reduce(value);return this;}public Water Drink() {if (this.State is LiquidState) {Console.WriteLine("You can drink!");}else {Console.WriteLine("You can not drink!");}Console.WriteLine(Const.LINE_BREAK);return this;}}

Water水类充当环境类,公开一个状态基类,并在内部维护一个温度。Increase调用State的升温,而Reduce调用State的降温,最后的Drink方法会因为水的状态的不同而拥有不同的行为。为了简化逻辑,在本例中,只有当水为液体时才能被饮用。

public abstract partial class State {public static Water Water { get; set; }protected static string StateName { private get; set; }public void Increase(int value) {if (value == 0) return;if (value < 0) throw new ArgumentException();OnStateChanging();Water.Temperature += value;ChangeState();}public void Reduce(int value) {if (value == 0) return;if (value < 0) throw new ArgumentException();if (Water.Temperature - value <= Const.ABSOLUTE_ZERO) {throw new UnReachableException();}OnStateChanging();Water.Temperature -= value;ChangeState();}}

抽象状态基类,首先公开一个水的引用,并在所有实现类中共享StateName状态名,Increase为水升高一个温度,而Reduce为水降温。

public abstract partial class State {private void ChangeState() {if (Water.Temperature <= 0) {Water.State = new SolidState();}else if (Water.Temperature > 0 && Water.Temperature < 100) {Water.State = new LiquidState();}else {Water.State = new GasState();}OnStateChanged();}protected virtual void OnStateChanging() {Console.WriteLine(Const.ON_STATE_CHANGING);Console.WriteLine(string.Format(Const.TEMPERATURE_INFO,Water.Temperature, StateName));}protected virtual void OnStateChanged() {Console.WriteLine(Const.ON_STATE_CHANGED);Console.WriteLine(string.Format(Const.TEMPERATURE_INFO,Water.Temperature, StateName));Console.WriteLine(Const.LINE_BREAK);}}

抽象状态基类的第2部分(partial ),定义ChangeState方法以在改变温度时更改状态,另外定义OnStateChanging和OnStateChanged这2个受保护的虚方法以便提供“子类可以决定是否重写相应的方法来影响父类”的这样一个功能(OOP特性)。

public class SolidState : State {public SolidState() {StateName = "Solid";}}
public class LiquidState : State {public LiquidState() {StateName = "Liquid";}}
public class GasState : State {public GasState() {StateName = "Gas";}}

水的3种状态的具体实现类,SolidState固体状态、LiquidState液体状态和GasState气体状态,由于我们在状态基类中封装了较多的功能,所以此处的3个具体类都比较精简,只在构造函数中更改共享的StateName状态名称字段。在实际开发过程中,应当尽可能的将具体的功能封装在状态实现类中。

public class Const {public const double ABSOLUTE_ZERO = -273.15;public const string LINE_BREAK ="--------------------------------------------------";public const string ON_STATE_CHANGING = "OnStateChanging()";public const string ON_STATE_CHANGED = "OnStateChanged()";public const string TEMPERATURE_INFO = "The temperature is {0} °C" +" and state name is {1}!";}

常量类,维护一些在本案例中经常使用到的字符串或数值。在实际开发过程中不应当有此类,应该将相应的常量放在具体要使用的类中。2017年,阿里发布《阿里巴巴Java开发手册》,其中有一节提到此准则,所有使用面向对象编程语言的开发人员都应当遵从。

public class UnReachableException : Exception {public UnReachableException(): base("Absolute zero cannot be reached!") {}public UnReachableException(string message, Exception innerException): base(message, innerException) {}}

绝对零度无法到达异常类UnReachableException,进行简单的异常处理。

public class Program {private static Water _water = new Water();public static void Main(string[] args) {try {_water.Increase(68).Drink().Increase(82).Drink().Reduce(90).Drink().Reduce(0).Reduce(80).Drink().Reduce(300).Drink();}catch (Exception ex) {Console.WriteLine(ex.Message);Console.WriteLine(Const.LINE_BREAK);}Console.ReadKey();}}

以上是本案例的调用方代码,升温方法Increase、降温方法Reduce和喝水方法Drink经过特别的处理以支持方法链。以下是这个案例的输出结果:

OnStateChanging()
The temperature is 0 °C and state name is Solid!
OnStateChanged()
The temperature is 68 °C and state name is Liquid!
--------------------------------------------------
You can drink!
--------------------------------------------------
OnStateChanging()
The temperature is 68 °C and state name is Liquid!
OnStateChanged()
The temperature is 150 °C and state name is Gas!
--------------------------------------------------
You can not drink!
--------------------------------------------------
OnStateChanging()
The temperature is 150 °C and state name is Gas!
OnStateChanged()
The temperature is 60 °C and state name is Liquid!
--------------------------------------------------
You can drink!
--------------------------------------------------
OnStateChanging()
The temperature is 60 °C and state name is Liquid!
OnStateChanged()
The temperature is -20 °C and state name is Solid!
--------------------------------------------------
You can not drink!
--------------------------------------------------
Absolute zero cannot be reached!
--------------------------------------------------

优点:

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/425 访问。

1、封装了转换规则;
2、枚举可能的状态,在枚举状态之前需要确定状态种类;
3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为;
4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块;
5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点:

1、状态模式的使用必然会增加系统类和对象的个数;
2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱;
3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

使用场景:

1、行为随状态改变而改变的场景;
2、条件、分支语句的代替者。

C#设计模式之20-状态模式相关推荐

  1. 【游戏设计模式】之三 状态模式、有限状态机 Unity版本实现

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://blog.csdn.net/poem_qianmo/article/details/52824776 作者:毛星云(浅 ...

  2. 【游戏设计模式】之三 状态模式 有限状态机 Unity版本实现

     本系列文章由@浅墨_毛星云 出品,转载请注明出处.    文章链接: http://blog.csdn.net/poem_qianmo/article/details/52824776  作者:毛星 ...

  3. 【游戏设计模式】之三 状态模式、有限状态机

    转载自:https://blog.csdn.net/poem_qianmo/article/details/52824776 游戏开发过程中,各种游戏状态的切换无处不在.但很多时候,简单粗暴的if e ...

  4. 设计模式之略见一斑(状态模式State)

    设计模式中的状态模式相对比较简单,简单的说就是对某个对象的状态进行管理.对象的状态如果的多的话,假如没有对其进行管理,极易造成管理混乱.从而使系统难以维护,所以State模式的意图就是将与状态有关的处 ...

  5. 设计模式C++实现 ——状态模式

    软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径.设计模式中运用了面向对象编程语言的重要特性:封装.继承.多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累.最 ...

  6. 设计模式:(状态模式)

    1.定义 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式. 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 co ...

  7. 设计模式学习笔记-状态模式

    引言 使用该设计模式的情况:如在场景中的主角甚至是敌人,有N个不同状态:走路,攻击,待机.....,游戏中,这些状态来回切换.有一个明确的状态划分的情况下,此时,是可以使用Switch...case. ...

  8. c语言lr分析器的设计与实现_Python3设计模式四 :状态模式

    状态(state)模式在实现上类似于策略模式,但是它们的目标非常的不同.状态模式呈现的是一个状态转换系统:系统中的对象处在一个特定的状态当中,经过某些操作之后可以抵达另外的状态. 为了实现这一目标,需 ...

  9. 从王者荣耀看设计模式(六.状态模式)

    从王者荣耀看设计模式(状态模式) 一.简介 英雄项羽在敌方英雄的攻击下存在3种不同的状态. 1.在健康生命值下--普通状态,在每次被攻击时,当前生命值=剩余生命值-敌方英雄伤害值 2.在生命值低于某一 ...

  10. 设计模式之 State(状态模式)通俗理解

    23种设计模式 1 State 模式的定义 不同的状态,不同的行为;或者说,每个状态有着相应的行为. 2 何时使用? 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了它的类.状态模式 ...

最新文章

  1. popStar手机游戏机机对战程序
  2. 色情低俗、暴力恐怖内容...如何用AI“一网打尽”?
  3. 从平台到中台 | Elaticsearch 在蚂蚁金服的实践经验
  4. Vue 实例生命周期
  5. vue中v-for的使用
  6. 列出我所知道的图像处理库
  7. 操作系统Ubuntu(实验一二)
  8. php psot传值_三种方法教你如何用PHP模拟post提交数据
  9. 就地链表反转_数据结构与算法系列之链表操作全集(二)(GO)
  10. struts的执行流程
  11. java代码sudo命令_讓Java程序運行sudo命令
  12. PROE_CONFIG
  13. 6.ring3-ImportREC重建输入表
  14. 怎么制定合理的开发计划
  15. 嵌入式方向的毕业生,找工作很迷茫
  16. 寒假宅喵java学习
  17. 联想主板bios设置u盘启动项的方法怎么操作
  18. cas java_什么是CAS?JAVA中哪些地方用到来CAS?
  19. 5G+智慧灯杆发展生态峰会闭幕,专家精彩观点汇总
  20. 【rpc】超详细介绍

热门文章

  1. 【C++基础学习】关于C++静态成员函数和变量
  2. 自定义异常 java
  3. 案例 项目经理评分 c# 1613922661
  4. photoshop cs6 安装过程 0920
  5. dj电商-数据表的设计-用户表设计
  6. css-样式的权重-圆角-rgba
  7. SQL Server添加索引
  8. 邮件安全之邮件认证技术
  9. 学习设计模式——工厂方法模式
  10. 京东家电渠道赋能战略加速落地,助力家电品牌打通人、货、场间隔