最近学习了设计模式行为型中的状态模式,这个模式的就完全体现出“多态”这种性质了,首先是它的解释:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
为什么说状态模式就体现出多态?在图上可以看出具体对象对应的状态行为有多个,而这个状态行为是由什么决定去使用呢?
主要还是通过具体对象Context这个对象的属性值的变化,通过属性值的变化我去执行一个操作(行为)时,决定使用下面三个状态行为哪一个。
在大话设计模式这本书中给状态模式举例说明的那个例子就很形象,同样一个行为,在时间不一样的时候展现出的效果是不一样的,这里的时间就是我们具体对象的属性(状态),对应到状态模式的解释中就是状态改变,而后者行为就是那个具体的动作,但是状态发生变化后他就也被改变了。
那么总结一下,这个状态模式的多态在具体的对象中体现出来的就是一个方法的实现,在不同属性(状态)下展现出来的行为是不一样的,而且这个状态模式的适用环境是一个相对确定的业务,如果想要对一个对象添加新的状态,那么这个具体的状态类只能放到原本第一个具体的状态类前面的位置,就像栈一样,这种情况下是属于可扩展的,但是相对于职责链的在外部设置上下级的这种方式还是有局限的。不过我相信还是有其他的符合开闭原则的方法来支持它的扩展性的。如果有的话希望各位不吝赐教,感谢
具体代码是根据书中例子来
抽象状态:
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); } }