原文:C#设计模式之十八状态模式(State Pattern)【行为型】
一、引言
今天我们开始讲“行为型”设计模式的第六个模式,该模式是【状态模式】,,英文名称是:State Pattern。无论是现实世界,还是面向东西的OO世界,里面都有一个对象,那就是东西。有东西固然就有状态了。每个东西都有其对应的状态,而每个状态又有对应一些相应的行为,在差别状态下,行为的的方法也是不一样。如果某个东西有多个状态时,那么就会有很多对应的行为。那么对这些状态的判断和按照状态完成的行为,就会导致多重条件语句交织在一起,并且如果添加一种新的状态时,需要变动之前现有的代码。这样的设计显然违背了开闭原则,状态模式正是用来解决这样的问题的。
二、状态模式的详细介绍
2.1、动机(Motivate)
在软件构建过程中,某些东西的状态如果转变,其行为也会随之而产生变革,好比文档处于只读状态,其撑持的行为和读写状态撑持的行为就可能完全差别。
如安在运行时按照东西的状态来透明地变动东西的行为?而不会为东西操纵和状态转化之间引入紧耦合?
2.2、意图(Intent)
允许一个东西在其内部状态转变时转变它的行为。从而使东西看起来似乎改削了其行为。 ——《设计模式》GoF
2.3、布局图(Structure)
2.4、模式的构成
可以看出,在状态模式的布局图有以下角色:
(1)、环境角色(Context):也称上下文,界说客户端所感兴趣的接口,并且保存一个具体状态类的实例。这个具体状态类的实例给出此环境东西的现有状态。
(2)、抽象状态角色(State):界说一个接口,用以封装环境东西的一个特定的状态所对应的行为。
(3)、具体状态角色(ConcreteState):每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
在状态模式布局中需要理解环境类与抽象状态类的感化:
环境类实际上就是拥有状态的东西,环境类有时候可以充当状态打点器(State Manager)的角色,可以在环境类中对状态进行切换操纵。
抽象状态类可以是抽象类,也可以是接口,差别状态类就是担任这个父类的差别子类,状态类的孕育产生是由于环境类存在多个状态,同时还满足两个条件:这些状态经常需要切换,在差此外状态下东西的行为差别。因此可以将差别东西下的行为单独提取出来封装在具体的状态类中,使得环境类东西在其内部状态转变时可以转变它的行为,东西看起来似乎改削了它的类,而实际上是由于切换到差此外具体状态类实现的。由于环境类可以设置为任一具体状态类,因此它针对抽象状态类进行编程,在措施运行时可以将任一具体状态类的东西设置到环境类中,从而使得环境类可以转变内部状态,并且转变行为。
2.5、状态模式的代码实现
状态模式在显示生活中也有类似的例子,例如:我们上网采办商品的过程中,就可以检察订单的状态随时状态。对付商家来说,订单的状态差别,也会允许客户有差此外行动要求,好比:订单在已经处于发货状态,此订单是不能退货的。如果订单在备货阶段,客户是可以换货或者退货的。如果我们的订单已经发货了,您就等着接收货物吧,如果货物有质量问题,可以拒签,或者顺利完成交易,今天我们就以订单为例来说明状态模式的实现。实现代码如下:
namespace 状态模式的实现 { //环境角色---相当于Context类型 public sealed class Order { private State current; public Order() { //事情状态初始化为上午事情状态 current = new WaitForAcceptance(); IsCancel = false; } private double minute; public double Minute { get { return minute; } set { minute = value; } } public bool IsCancel { get; set; } private bool finish; public bool TaskFinished { get { return finish; } set { finish = value; } } public void SetState(State s) { current = s; } public void Action() { current.Process(this); } } //抽象状态角色---相当于State类型 public interface State { //措置惩罚惩罚订单 void Process(Order order); } //期待受理--相当于具体状态角色 public sealed class WaitForAcceptance : State { public void Process(Order order) { System.Console.WriteLine("我们开始受理,筹备备货!"); if (order.Minute < 30 && order.IsCancel) { System.Console.WriteLine("接受半个小时之内,可以打消订单!"); order.SetState(new CancelOrder()); order.TaskFinished = true; order.Action(); } order.SetState(new AcceptAndDeliver()); order.TaskFinished = false; order.Action(); } } //受理发货---相当于具体状态角色 public sealed class AcceptAndDeliver : State { public void Process(Order order) { System.Console.WriteLine("我们货物已经筹备好,可以发货了,不成以勾销订单!"); if (order.Minute < 30 && order.IsCancel) { System.Console.WriteLine("接受半个小时之内,可以打消订单!"); order.SetState(new CancelOrder()); order.TaskFinished = true; order.Action(); } if (order.TaskFinished==false) { order.SetState(new Success()); order.Action(); } } } //交易告成---相当于具体状态角色 public sealed class Success : State { public void Process(Order order) { System.Console.WriteLine("订单结算"); order.SetState(new ConfirmationReceipt()); order.TaskFinished = true; order.Action(); } } //确认收货---相当于具体状态角色 public sealed class ConfirmationReceipt : State { public void Process(Order order) { System.Console.WriteLine("查抄货物,没问题可以就可以签收!"); order.SetState(new ConfirmationReceipt()); order.TaskFinished = true; order.Action(); } } //打消订单---相当于具体状态角色 public sealed class CancelOrder : State { public void Process(Order order) { System.Console.WriteLine("查抄货物,有问题,打消订单!"); order.SetState(new CancelOrder()); order.TaskFinished = true; order.Action(); } } public class Client { public static void Main(String[] args) { //订单 Order order = new Order(); order.Minute = 9; order.Action(); //可以打消订单 order.IsCancel = true; order.Minute = 20; order.Action(); order.Minute = 33; order.Action(); order.Minute = 43; order.Action(); Console.Read(); } } }