设计模式21——行为型模式之状态模式

定义状态模式(State Pattern),允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

类型对象行为型模式

概述:

         一个对象有一个状态,那么每一个状态又对应一些相应的行为。如果这个对象有很多状态,那么就要对应非常多的行为。那么对这些状态的判断以及根据状态完成相应的行为,会非常复杂。并且如果想添加一种新的状态时,需要修改很多的现有代码。这也是有违开闭原则的。状态模式正是在这样一种情况下提出来的。

        状态模式将每种状态对应的行为抽象出来成为单独的新的对象,这样将状态转换显式化了。状态的变换不再依赖于Context内部的行为了。另外,将状态及行为提出来能够大为降低Context对象的复杂度。另外如果一个State对应多个Context时,State还可以被多个Context对象共享。

        状态,我们立马会提出,今天状态不好,做什么都没劲;又或者是今天状态很好,做事得劲,饭也吃得多。那么我们就以一个人不同时刻的状态为例来讲解状态模式。

类图:

参与者:

  1. Human,也即Context通过抽象接口来调用状态对象的具体实现。
  1. State,封装了与Human相关行为的接口。
  1. HappySad,具体实现了与相应状态下的行为。

示例代码:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4.   
  5. namespace Pattern21  
  6. {  
  7.     //抽象状态   
  8.     public abstract class State  
  9.     {  
  10.         public abstract void Eat();  
  11.         public abstract void Walk();  
  12.     }  
  13.   
  14.     // 高兴时的状态   
  15.     public class Happy : State  
  16.     {  
  17.         public override void Eat()  
  18.         {  
  19.             human.Eat();  
  20.             Console.WriteLine("很多!");  
  21.         }  
  22.   
  23.         public override void Walk()  
  24.         {  
  25.             human.Walk();  
  26.             Console.WriteLine("手舞足蹈的!");  
  27.         }  
  28.   
  29.         public void Attach(Human _human)  
  30.         {  
  31.             human = _human;  
  32.         }  
  33.   
  34.         private Human human;  
  35.     }  
  36.   
  37.     // 伤心时的状态   
  38.     public class Sad : State  
  39.     {  
  40.         public override void Eat()  
  41.         {  
  42.             human.Eat();  
  43.             Console.WriteLine("很少!");  
  44.         }  
  45.   
  46.         public override void Walk()  
  47.         {  
  48.             human.Walk();  
  49.             Console.WriteLine("无精打采的!");  
  50.         }  
  51.   
  52.         public void Attach(Human _human)  
  53.         {  
  54.             human = _human;  
  55.         }  
  56.   
  57.         private Human human;  
  58.     }  
  59.      
  60.   
  61.     // 一个人   
  62.     public class Human  
  63.     {  
  64.         private State current;  
  65.   
  66.         public void SetState(State s)  
  67.         {  
  68.             current = s;  
  69.         }  
  70.   
  71.         public void Eat()  
  72.         {  
  73.             Console.Write("吃了");  
  74.         }  
  75.   
  76.         public void Walk()  
  77.         {  
  78.             Console.Write("走起路来");  
  79.         }  
  80.   
  81.         public void Show()  
  82.         {  
  83.             current.Eat();  
  84.             current.Walk();  
  85.         }  
  86.     }  
  87.     class Program  
  88.     {  
  89.         static void Main(string[] args)  
  90.         {  
  91.             // 定义一个有很多状态的对象   
  92.             Human human = new Human();  
  93.   
  94.             // 定义一个高兴的状态   
  95.             Happy hState = new Happy();  
  96.             hState.Attach(human);  
  97.             human.SetState(hState);  
  98.             human.Show();  
  99.   
  100.             // 定义一个伤心的状态   
  101.             Sad sad = new Sad();  
  102.             sad.Attach(human);  
  103.             human.SetState(sad);  
  104.             human.Show();  
  105.   
  106.             // 还可以添加生病的状态,只需要添加新的类而不需要修改Human类   
  107.             // ......   
  108.   
  109.             Console.Read();  
  110.         }  
  111.     }  
  112. }  

适用性:

  1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  2. 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

优缺点:

  1. 优点,将状态判断的逻辑移到类外面,方便通过添加新类来添加新的状态。
  2. 缺点,如果状态非常多,会导致有非常多的状态类,加大开销。

参考资料:

  1. 《设计模式——可复用面向对象软件基础》
  2. 《大话设计模式》
原文地址:https://www.cnblogs.com/feihe0755/p/3597664.html