状态模式(State)定义:当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
什么是状态:
应用程序中的部分对象可能会根据不同的情况做出不同的行为,我们把这种对象称为有状态的对象,而把影响对象行为的一个或多个动态变化的属性称为状态
优点:
- 将与特定状态相关的行为放到该状态中,并且将不同状态下的行为分割开来,消除了选择语句,满足“单一职责原则”
- 将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
- 状态类职责明确,有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
缺点:
- 必然会增加系统的类与对象的个数。
- 结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
- 不利于实现开闭原则,对于可以切换状态的状态模式,增加新的状态类需要修改那些负- 责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。
模式的结构
环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
代码背景:打工人从早到晚打工的精神状态。
抽象状态类:
public abstract class State { public abstract void WriteProgram(Work w); }
具体状态类:
//上午工作状态 public class ForenoonState : State { public override void WriteProgram(Work w) { if (w.Hour < 12) { Console.WriteLine("当前时间:{0}点 上午工作,精神百倍",w.Hour); } else { w.SetState(new NoonState());w.WriteProgram(); } } } //中午工作状态 public class NoonState : State { public override void WriteProgram(Work w) { if (w.Hour < 13) { Console.WriteLine("当前时间:{0}点 饿了,想吃饭;犯困,想睡觉。", w.Hour); } else { w.SetState(new AfternoonState()); w.WriteProgram(); } } } //下午工作状态 public class AfternoonState : State { public override void WriteProgram(Work w) { if (w.Hour < 17) { Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力", w.Hour); } else { w.SetState(new EveningState()); w.WriteProgram(); } } } //晚上工作状态 public class EveningState : State { public override void WriteProgram(Work w) { if (w.TaskFinished) { w.SetState(new RestState());w.WriteProgram();//完成任务就转成下班状态 } else { if (w.Hour <21) { Console.WriteLine("当前时间:{0}点 加班了,加班人累啊", w.Hour); } else { w.SetState(new SleepingState()); w.WriteProgram();//超过21点,转入睡眠状态 } } } } //睡眠状态 public class SleepingState:State { public override void WriteProgram(Work w) { Console.WriteLine("当前时间:{0}点 不行了,睡着了", w.Hour); } } //下班休息状态 public class RestState : State { public override void WriteProgram(Work w) { Console.WriteLine("当前时间:{0}点 不行了,睡着了", w.Hour); } }
工作类(环境类):
public class Work { private State current; public Work() { current = new ForenoonState(); //初始化为上午9点开始上班 } private double hour; public double Hour //小时钟,状态转换的依据 { get { return hour; } set { hour = value; } } private bool finish = false; public bool TaskFinished //完成任务属性,是否能下班的依据 { get { return finish; } set { finish = value; } } public void SetState(State s) //得到状态 { current = s; } public void WriteProgram() { current.WriteProgram(this); } }
客户端:
static void Main(string[] args) { Work emergencyProjects = new Work(); emergencyProjects.Hour = 9; emergencyProjects.WriteProgram(); emergencyProjects.Hour = 10; emergencyProjects.WriteProgram(); emergencyProjects.Hour = 12; emergencyProjects.WriteProgram(); emergencyProjects.Hour = 13; emergencyProjects.WriteProgram(); emergencyProjects.Hour = 14; emergencyProjects.WriteProgram(); emergencyProjects.Hour = 17; emergencyProjects.TaskFinished = false;//未完成任务,加班 emergencyProjects.WriteProgram(); emergencyProjects.Hour = 19; emergencyProjects.WriteProgram(); emergencyProjects.Hour = 22; emergencyProjects.WriteProgram(); Console.Read(); }