C# 设计模式系列教程-状态模式

1. 概述

  当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

2. 解决的问题

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

3. 模式中的角色

  3.1 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。

  3.2 抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。

  3.3 具体状态(Concrete State):实现抽象状态定义的接口。

4. 模式解读

  4.1 状态模式的类图

  4.2 状态模式的代码实现

 /// <summary>
 /// Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
 /// </summary>
 public class Context
 {
  private State state;
  /// <summary>
  /// 定义Context的初始状态
  /// </summary>
  /// <param name="state"></param>
  public Context(State state)
  {
   this.state = state;
  }

  /// <summary>
  /// 可读写的状态属性,用于读取和设置新状态
  /// </summary>
  public State State
  {
   get { return state; }
   set { state = value; }
  }

  /// <summary>
  /// 对请求做处理,并设置下一个状态
  /// </summary>
  public void Request()
  {
   state.Handle(this);
  }
 }

 /// <summary>
 /// 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
 /// </summary>
 public abstract class State
 {
  public abstract void Handle(Context context);
 }

 /// <summary>
 /// 具体状态类,每一个子类实现一个与Context的一个状态相关的行为
 /// </summary>
 public class ConcreteStateA : State
 {
  /// <summary>
  /// 设置ConcreteStateA的下一个状态是ConcreteStateB
  /// </summary>
  /// <param name="context"></param>
  public override void Handle(Context context)
  {
   Console.WriteLine("当前状态是 A.");
   context.State = new ConcreteStateB();
  }
 }

 public class ConcreteStateB : State
 {
  /// <summary>
  /// 设置ConcreteStateB的下一个状态是ConcreteSateA
  /// </summary>
  /// <param name="context"></param>
  public override void Handle(Context context)
  {
   Console.WriteLine("当前状态是 B.");
   context.State = new ConcreteStateA();
  }
 }

  4.3 客户端调用

 class Program
 {
  static void Main(string[] args)
  {
   // 设置Context的初始状态为ConcreteStateA
   Context context = new Context(new ConcreteStateA());

   // 不断地进行请求,同时更改状态
   context.Request();
   context.Request();
   context.Request();
   context.Request();

   Console.Read();
  }
 }

  运行结果

5. 模式总结

  5.1 优点

    5.1.1 状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。

    5.1.2 所有状态相关的代码都存在于某个ConcereteState中,所以通过定义新的子类很容易地增加新的状态和转换。

    5.1.3 状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。

  5.2 缺点

    5.2.1 导致较多的ConcreteState子类

  5.3 适用场景

    5.3.1 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式来。

    5.3.2 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态。

6. 应用举例:电灯有两个状态,开(亮)与关(不亮),下面就用状态模式来实现对电灯的控制。

  6.1 类图

  6.2 实现代码

 /// <summary>
 /// 电灯类,对应模式中的Context类
 /// </summary>
 public class Light
 {
  private LightState state;

  public Light(LightState state)
  {
   this.state = state;
  }

  /// <summary>
  /// 按下电灯开关
  /// </summary>
  public void PressSwich()
  {
   state.PressSwich(this);
  }

  public LightState State
  {
   get { return state; }
   set { state = value; }
  }
 }

 /// <summary>
 /// 抽象的电灯状态类,相当于State类
 /// </summary>
 public abstract class LightState
 {
  public abstract void PressSwich(Light light);
 }

 /// <summary>
 /// 具体状态类, 开
 /// </summary>
 public class On : LightState
 {
  /// <summary>
  /// 在开状态下,按下开关则切换到关的状态。
  /// </summary>
  /// <param name="light"></param>
  public override void PressSwich(Light light)
  {
   Console.WriteLine("Turn off the light.");

   light.State = new Off();
  }
 }

 /// <summary>
 /// 具体状态类,关
 /// </summary>
 public class Off: LightState
 {
  /// <summary>
  /// 在关状态下,按下开关则打开电灯。
  /// </summary>
  /// <param name="light"></param>
  public override void PressSwich(Light light)
  {
   Console.WriteLine("Turn on the light.");

   light.State = new On();
  }
 }

  6.3 客户端代码


 class Program
 {
  static void Main(string[] args)
  {
   // 初始化电灯,原始状态为关
   Light light = new Light(new Off());

   // 第一次按下开关,打开电灯
   light.PressSwich();
   // 第二次按下开关,关闭电灯
   light.PressSwich();

   Console.Read();
  }
 }

  执行结果

(0)

相关推荐

  • C#设计模式之单例模式实例讲解

    前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高.保证代码可靠性.所谓设计模式,我找了下定义:是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 为什么要提倡"Design Pattern(设计模式)"? 根本原因是为了代码复用,增加可维护性.因此这次我们来学习下设计模式,最后会通过C#语言来实现这些设计模式作为例子,深刻

  • C# 设计模式系列教程-策略模式

    在讲策略模式之前,我先给大家举个日常生活中的例子,从首都国际机场到XXX酒店,怎么过去?1)酒店接机服务,直接开车来接.2)打车过去.3)机场快轨+地铁 4)机场巴士 5)公交车 6)走路过去(不跑累死的话) 等等.使用方法,我们都可以达到从机场到XXX酒店的目的,对吧.那么我所列出的从机场到XXX酒店的的方法,就是我们可以选择的策略. 再举个例子,就是我们使用WCF时,往往避免不了对它进行扩展,例如授权,我们可以通过自定义授权来扩展WCF.这里我们可以通过自定义AuthorizationPol

  • 实例解析C#设计模式编程中简单工厂模式的使用

    简单工厂模式的介绍 说到简单工厂,自然的第一个疑问当然就是什么是简单工厂模式了? 在现实生活中工厂是负责生产产品的,同样在设计模式中,简单工厂模式我们也可以理解为负责生产对象的一个类, 我们平常编程中,当使用"new"关键字创建一个对象时,此时该类就依赖与这个对象,也就是他们之间的耦合度高,当需求变化时,我们就不得不去修改此类的源码,此时我们可以运用面向对象(OO)的很重要的原则去解决这一的问题,该原则就是--封装改变,既然要封装改变,自然也就要找到改变的代码,然后把改变的代码用类来封

  • C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    本文实例讲述了C#设计模式之Strategy策略模式解决007大破密码危机问题.分享给大家供大家参考,具体如下: 一.理论定义 策略模式 定义了 多套算法,这些算法在 客户端 可以任意切换. 二.应用举例 需求描述:话说007在皇家赌场赌牌,突然接到M夫人的急电,要求立刻去非洲 寻找一个DES对称算法密钥,以破解敌人的军*情*机*密 1.(英*国*军*情*六*局)MI6=Military Intelligence 6  截获了 一个非*洲战*区军*事*机*密文件,采用 MD5,RAS,加密,解密

  • C#设计模式之Observer观察者模式解决牛顿童鞋成绩问题示例

    本文实例讲述了C#设计模式之Observer观察者模式解决牛顿童鞋成绩问题.分享给大家供大家参考,具体如下: 一.理论定义 观察者模式 描述了 一种 一对多的关系. 当某一对象的状态发生改变时,其他对象会得到 改变的通知.并作出相应的反应. 二.应用举例 需求描述:牛顿同学的期末考试成绩(Score)出来了,各科老师都想知道自己的 学生 成绩情况! 语文老师(TeacherChinese)只关心  牛顿的语文(Chinese)成绩. 英语老师(TeacherEnglish)只关心  牛顿的英语(

  • C#设计模式之观察者模式实例讲解

    前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高.保证代码可靠性.所谓设计模式,我找了下定义:是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.毫无疑问,设计模式于己于他人于系统都是多赢的:设计模式使代码编制真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 为什么要提倡"Design Pattern(设计模式)"? 根本原因是为了代码复用,增加可维护性.因此这次我们来学习下设计模式,最后会通过C#语言来实现这些设计模式作为例子,深刻

  • C#设计模式之Mediator中介者模式解决程序员的七夕缘分问题示例

    本文实例讲述了C#设计模式之Mediator中介者模式解决程序员的七夕缘分问题.分享给大家供大家参考,具体如下: 一.理论定义 中介者模式  定义了一种一对多的操作,解脱了对象之间多对多的引用依赖,所有对象之间的通信,都封装在 中介者里面. 二.应用举例 需求描述: 七夕来啦,谁说程序员就一定 是单身苦逼呢,程序员也有自己的幸福. 也在追寻自己的缘分,我们都是有理想,有文化,有独立见解的群体, 我们为 信息社会所做的努力,能给我们七夕带来好运.告别单身,开始行动啦! 1.三个程序员 找到了 缘分

  • C#设计模式之Visitor访问者模式解决长隆欢乐世界问题实例

    本文实例讲述了C#设计模式之Visitor访问者模式解决长隆欢乐世界问题.分享给大家供大家参考,具体如下: 一.理论定义 访问者模式 提供了 一组 集合 对象 统一的 访问接口,适合对 一个集合中的对象,进行逻辑操作,使 数据结构  和 逻辑结构分离. 二.应用举例 需求描述:暑假来啦!三个小伙子组团,开车来 长隆欢乐世界玩. 每个人想玩的项目都不一样, 旅游者 1   想玩:十环过山车,龙卷风暴,梦幻旋马 旅游者 2   想玩:空中警察,欢乐摩天轮,超级水战 旅游者 3   想玩:四维影院,垂

  • C#设计模式之外观模式介绍

    1.在设计初期阶段,应该要有意识的将不同的两层分离,比如考虑数据访问层.业务逻辑层.表示层之间建立外观模式,这样可以为子系统提供简单一致的接口,使得耦合大大降低. 2.开发阶段,子系统内部由于不够重构变得非常复杂,增加外观模式可以屏蔽这个复杂性,并提供简单的接口. 3.维护一个遗留的大型系统,代码不好再维护时,使用外观模式也是不错的选择. 看看外观模式的结构图: Facade类定义:可以给高层系统提供简单的接口 复制代码 代码如下: class Facade { SubSystemOne one

  • c#设计模式 适配器模式详细介绍

    后续内容将包括以下结构模式: 适配器模式(Adapter):Match interfaces of different classes合成模式(Composite):A tree structure of simple and composite objects装饰模式(Decorator):Add responsibilities to objects dynamically代理模式(Proxy):An object representing another object享元模式(Flywei

  • C#设计模式之ChainOfResponsibility职责链模式解决真假美猴王问题实例

    本文实例讲述了C#设计模式之ChainOfResponsibility职责链模式解决真假美猴王问题.分享给大家供大家参考,具体如下: 一.理论定义 职责链模式 向一个 对象提出一个请求,如果这个对象无法处理这个请求,将指定下一个对象来处理这个请求, 直到这个请求能得到处理为止. 二.应用举例 需求描述:<西游记>里面的真假美猴王的辨别过程 六耳猕猴和孙悟空不仅外型一模一样,本事也是一模一样,走到哪儿,都无法分辨谁是真的谁是假的! ① 观音菩萨(GuangYinBodhisattva)暗念<

随机推荐