zoukankan      html  css  js  c++  java
  • 设计模式学习之-状态模式

    一、状态模式
    状态模式,当一个对象的内在状态发生改变时允许改变其行为行为,这个对象像是改变了其子类。状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同的状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断比较简单,那就没有必要用“状态模式”了。这段话有点难以理解,简而言之就是,在一类中根据当前状态去实例化下一状态子类。下面是状态模式结构图。

    State类,是一个抽象状态类,定义一个接口以封装与Context的特定状态相关的行为。

    1 public abstract class State
    2 {
    3     public abstract void Handl(Context context);
    4 }

    ConcreateState类,是具体的状态类,继承State类,每一个子类实现一个与Context的一个状态相关的行为。

     1 public class ConcreateStateA:State
     2 {
     3     public void Handl(Context context)
     4     {
     5         //设置ConcreateStateA的下一个状态ConcreateStateB
     6         context.State=new ConcreateStateB();
     7     }
     8 }
     9 
    10 public class ConcreateStateB:State
    11 {
    12     public void Handl(Context context)
    13     {
    14         //设置ConcreateStateB的下一个状态ConcreateStateA
    15         context.State=new ConcreateStateA();
    16     }
    17 }
    View Code

    Context类,维护一个ConcreateState子类的实例,在这个实例中定义当前的状态。

     1 public class Context
     2 {
     3     private State state;
     4     public Context(State state)
     5     {    
     6         //在构造函数中初始化Context的初始状态。
     7         state=state);
     8     }
     9     //可读写的状态属性,用于读取当前状态和设置新状态
    10     public State State
    11     {
    12         get
    13         {
    14             return this.state;
    15         }
    16         set
    17         {
    18             this.state=value;
    19             Conole.WriteLine("当前状态时:{0}",state.GetType().Name);
    20         }
    21     }
    22 
    23     public void Request()
    24     {
    25         //对请求做处理,并设置下一状态
    26         state.Handle(this);
    27     }
    28 
    29 }

    客户端调用代码:

     1 static void main(string [] args)
     2 {
     3     
     4     Context context=new Context(new ConcreateStateA());//设置Context的初始化状态为ConcreateState
     5     context.Request();
     6     context.Request();
     7     context.Requset();
     8     context.Requset();
     9 
    10     Console.ReadKey();    
    11 }

    [运行结果图]

    二、状态模式好处与用处
    状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来,这样做的目的是为了消除庞大的条件分支语句,大的分支判断会使得他们难以修改和扩展,任何改动和变化都会是程序出现致命错误。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
    在什么时候使用状态模式呢?
    当一个对象的行为取决于他的状态,并且他必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式。另外如果业务需求某项业务有多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的多分支判断语句来实现,此时应该考虑将每一种业务状态定义为一个State的子类,这样这些对象就可以不依赖其他对象而独立变化了。

    三、上班途中-状态模式

    先来看一下代码结构图

    抽象WaitingBus类,定义了一个WaitBus方法,需要一个OnRoad对象参数。

    1  public abstract class WaitingBus
    2     {
    3         public abstract void WaitBus(OnRoad road);
    4     }

    早上从家出发等公交车的状态类。

     1 /// <summary>
     2     /// 离开家,去站台等车
     3     /// </summary>
     4     public class LeaveHome:WaitingBus
     5     {
     6         public override void WaitBus(OnRoad road)
     7         {
     8             if (road.BusCome == "还未进站")
     9             {
    10                 Console.WriteLine("当前状态:{0},心情焦急,上班要迟到了。", road.BusCome);
    11             }
    12             else
    13             {
    14                 road.WaiteBus = new BusComing();
    15                 road.Road();
    16 
    17             }
    18         }
    19     }

    公交车准备进站的状态类。

     1 /// <summary>
     2     /// 汽车准备进站,等待上车
     3     /// </summary>
     4     public class BusComing:WaitingBus
     5     {
     6         public override void WaitBus(OnRoad road)
     7         {
     8             if (road.BusCome == "准备进站")
     9             {
    10                 Console.WriteLine("当前状态时:{0},等待上车,心情激动,上班不能迟到了。", road.BusCome);
    11             }
    12             else
    13             {
    14                 road.WaiteBus = new BusComedGetOn();//转入下一状态
    15                 road.Road();//对下一状态请求做处理
    16             }
    17         }
    18     }

    公交车进站,上车是的状态类。

     1 /// <summary>
     2     /// 公共汽车进站,开始上车
     3     /// </summary>
     4     public class BusComedGetOn:WaitingBus
     5     {
     6         public override void WaitBus(OnRoad road)
     7         {
     8             if (road.BusCome == "上车")
     9             {
    10                 Console.WriteLine("当前状态时:{0},上车了,赶紧找个没人的位子,心情倍儿爽。", road.BusCome);
    11             }
    12             else
    13             {
    14                 road.WaiteBus = new OnRoading();
    15                 road.Road();
    16             }
    17         }
    18     }

    公交车在行驶途中的状态类。

     1 /// <summary>
     2     /// 公共汽车在去公司的路上,行驶中
     3     /// </summary>
     4     public class OnRoading:WaitingBus
     5     {
     6         public override void WaitBus(OnRoad road)
     7         {
     8             if (road.BusCome == "行驶中")
     9             {
    10                 Console.WriteLine("当前状态时:{0},手机上网看看新闻。咦,旁边站着老太太,赶紧让座。", road.BusCome);
    11             }
    12             else
    13             {
    14                 road.WaiteBus = new Arrival();
    15                 road.Road();
    16             }
    17         }
    18     }

    到达目的地的状态类。

     1 /// <summary>
     2     /// 汽车到站,下车去公司
     3     /// </summary>
     4     public class Arrival:WaitingBus
     5     {
     6         public override void WaitBus(OnRoad road)
     7         {
     8             Console.WriteLine("当前状态:{0},终于到站了,赶紧下车去公司。还有10分钟,舒了一口气。",road.BusCome);
     9         }
    10     }

    客户端调用代码:

     1 class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             OnRoad road = new OnRoad(new LeaveHome());
     6             road.BusCome = "还未进站";
     7             road.Road();
     8             road.BusCome = "准备进站";
     9             road.Road();
    10             road.BusCome = "上车";
    11             road.Road();
    12             road.BusCome = "行驶中";
    13             road.Road();
    14             road.BusCome = "到站";
    15             road.Road();
    16 
    17                 Console.ReadKey();
    18 
    19             }
    20     }

    程序运行结果如下:

     Demo下载

    个人网站多多支持:http://www.itguoguo.com

  • 相关阅读:
    MFC中CTREECTRL的checkbox问题
    GLOG的使用说明
    安装Electron
    WIN32中DLL的建立
    MFC动态创建菜单
    C++迭代器
    VIM常用命令
    层次遍历二叉树
    sql存储过程中加引号
    Apache Tomcat 绿色版安装Service(服务)
  • 原文地址:https://www.cnblogs.com/wangpf/p/3809446.html
Copyright © 2011-2022 走看看