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

  • 2019 年 10 月 5 日
  • 筆記

状态模式(State):

  在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理。最直接的解决方案是将这些所有可能发生的情况全都考虑到,然后使用if else语句来做状态判断来进行不同情况的处理。但对复杂状态的判断就显得”力不从心了”,随着增加新的状态或者修改一个状体if else(或switch case)语句的增多或者修改)可能会引起很大的修改,违反OCP原则状态模式就是在当控制一个对象状态转换的条件表达式过于复杂时,把相关”判断逻辑”提取出来,放到一系列的状态类当中,这样可以把原来复杂的逻辑判断简单化。

状态模式的角色:

  

  1)环境类(Context):也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。

  2)抽象状态类(AbstractState):定义一个接口以封装与Context的一个特定状态相关的行为。

  3)具体状态类(ConcreteState):实现抽象状态所对应的行为。

状态模式的代码实现: 

 1 internal class Program   2 {   3     private static void Main(string[] args)   4     {   5         // Setup context in a state   6         Context c = new Context(new ConcreteStateA());   7   8         // Issue requests, which toggles state   9         c.Request();  10         c.Request();  11     }  12 }  13  14 public abstract class AbstractState  15 {  16     public abstract void Handler(Context context);  17 }  18  19 public class Context  20 {  21     private AbstractState state;  22  23     public Context(AbstractState state)  24     {  25         this.state = state;  26     }  27  28     public AbstractState State  29     {  30         get  31         {  32             return state;  33         }  34         set  35         {  36             state = value;  37             Console.WriteLine("State: " + state.GetType().Name);  38         }  39     }  40  41     public void Request()  42     {  43         state.Handler(this);  44     }  45 }  46  47 public class ConcreteStateA : AbstractState  48 {  49     public override void Handler(Context context)  50     {  51         context.State = new ConcreteStateB();  52     }  53 }  54  55 public class ConcreteStateB : AbstractState  56 {  57     public override void Handler(Context context)  58     {  59         context.State = new ConcreteStateC();  60     }  61 }  62  63 public class ConcreteStateC : AbstractState  64 {  65     public override void Handler(Context context)  66     {  67         context.State = new ConcreteStateA();  68     }  69 }

实例:(以电灯开关为例) 

 1 internal class Program   2 {   3     private static void Main(string[] args)   4     {   5         Light light = new Light(new LightOff());   6         light.PressSwich();   7         light.PressSwich();   8     }   9 }  10  11 /// <summary>  12 /// 抽象电灯状态类  13 /// </summary>  14 public abstract class LightState  15 {  16     public abstract void PressSwich(Light light);  17 }  18  19 public class Light  20 {  21     private LightState state;  22  23     public Light(LightState state)  24     {  25         this.state = state;  26     }  27  28     public LightState State  29     {  30         get { return state; }  31         set { state = value; }  32     }  33  34     public void PressSwich()  35     {  36         state.PressSwich(this);  37     }  38 }  39  40 /// <summary>  41 /// 电灯打开状态  42 /// </summary>  43 public class LightOn : LightState  44 {  45     public override void PressSwich(Light light)  46     {  47         Console.WriteLine("Turn off the light.");  48         light.State = new LightOff();  49     }  50 }  51  52 /// <summary>  53 /// 电灯关闭状态  54 /// </summary>  55 public class LightOff : LightState  56 {  57     public override void PressSwich(Light light)  58     {  59         Console.WriteLine("Turn on the light.");  60         light.State = new LightOn();  61     }  62 }

状态模式的优缺点:

  优点:

    1)状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。

    2)减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。

    3)有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。

  缺点:

    1)状态模式的使用必然会增加系统的类与对象的个数。

    2)状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。

状态模式的应用场景:

  1)当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。

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

状态模式与策略模式的区别:

  从UML图上我们会发现这两种设计模式几乎一摸一样,都是利用多态把一些操作分配到一组相关的简单的类中。然而在显示世界中,策略模式和状态模式是两种完全不同的思想。对状态进行建模时,状态迁移是一个核心问题;但策略模式与迁移毫无关系,策略模式允许一个客户选择或提供一种策略。

状态模式与责任链模式的区别:

  职责链模式和状态模式都可以解决if分支过多的问题,从定义来看,状态模式是一个对象内在状态发生改变(一个对象,相对稳定,处理完一个对象下一个对象一般已确定),而职责链模式是多个对象之间的改变(多个对象之间的话,就会出现某个对象不存在的问题,且该模式由客户端指定,不稳定),这也说明了这两个模式处理的情况不同。

参考:https://www.runoob.com/w3cnote/state-vs-strategy.html

  https://blog.csdn.net/hguisu/article/details/7557252

Exit mobile version