设计模式(十二)状态模式
状态模式(State),当一个对象的内置状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复制的判断逻辑简化。
优点:
将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。也就是说,将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个 ConcreteState 中,所以通过定义新的子类可以很容易地增加新的状态和转换。
状态模式通过把各种状态转移逻辑分布到 State 的子类之间,来减少相互间的依赖。可以消除庞大的条件分支语句。
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
基本代码
1 // 抽象状态类,定义一个接口以封装与 Context 的一个特定状态相关的行为 2 abstract class State 3 { 4 public abstract void Handle(Context context); 5 } 6 7 // ConcreteState 具体状态类,每一个子类实现一个与 Context 的一个状态相关的行为 8 class ConcreteStateA : State 9 { 10 public override void Handle(Context context) 11 { 12 context.State = new ConcreteStateB(); // 设置下一状态 13 } 14 } 15 class ConcreteStateB : State 16 { 17 public override void Handle(Context context) 18 { 19 context.State = new ConcreteStateA(); // 设置下一状态 20 } 21 } 22 23 // Context 类维护一个 ConcreteState 子类的实例,这个实例定义当前的状态 24 class Context 25 { 26 private State state; 27 public Context(State state) 28 { 29 this.state = state; 30 } 31 32 // 可读写的状态属性,用于读取当前状态和设置新状态 33 public State State 34 { 35 get { return state; } 36 set 37 { 38 state = value; 39 Console.WriteLine("当前状态:" + state.GetType().Name); 40 } 41 } 42 43 // 对请求做处理,并设置下一状态 44 public void Request() 45 { 46 state.Handle(this); 47 } 48 } 49 50 // 客户端 51 static void Main(string[] args) 52 { 53 Context c = new Context(new ConcreteStateA()); 54 c.Request(); 55 56 Console.Read(); 57 }
【例】工作状态
部分代码
1 // 抽象状态 2 public abstract class State 3 { 4 public abstract void WriteProgram(Work w); 5 } 6 7 // 工作 8 public class Work 9 { 10 private State current; 11 public Work() 12 { 13 current = new ForenoonState(); 14 } 15 16 private double hour; 17 public double Hour 18 { 19 get { return hour; } 20 set { hour = value; } 21 } 22 23 private bool finish = false; 24 public bool TaskFinished 25 { 26 get { return finish; } 27 set { finish = value; } 28 } 29 30 public void SetState(State s) 31 { 32 current = s; 33 } 34 35 public void WriteProgram() 36 { 37 current.WriteProgram(this); 38 } 39 }