1、状态模式(State Pattern) 对象状态影响对象行为:对象拥有不同的状态,往往会行使不同的行为.动机:在软件构建过程中,某些对象的状态如果改变以及其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。如何在运行时根据对象的状态来透明更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?意图:允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。 - 设计模式GOF结构图:适用性:1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。2.一个操作中含有庞大的多分支的等条件语句,且这些分支依赖于该对
2、象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State 模式将每一个分支放入一个独立的类中。这使得你可根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。代码实现:class MainAppstatic void Main()/ Open a new accountAccount account = new Account(“Jim Johnson“);/ Apply financial transactionsaccount.Deposit(500.0);account.Deposit(300.0);account.
3、Deposit(550.0);account.PayInterest();account.Withdraw(2000.00);account.Withdraw(1100.00);/ Wait for userConsole.Read();/ “State“abstract class Stateprotected Account account;protected double balance;protected double interest;protected double lowerLimit;protected double upperLimit;/ Propertiespublic
4、Account Accountget return account; set account = value; public double Balanceget return balance; set balance = value; public abstract void Deposit(double amount);public abstract void Withdraw(double amount);public abstract void PayInterest();/ “ConcreteState“/ Account is overdrawnclass RedState : St
5、atedouble serviceFee;/ Constructorpublic RedState(State state)this.balance = state.Balance;this.account = state.Account;Initialize();private void Initialize()/ Should come from a datasourceinterest = 0.0;lowerLimit = -100.0;upperLimit = 0.0;serviceFee = 15.00;public override void Deposit(double amou
6、nt)balance += amount;StateChangeCheck();public override void Withdraw(double amount)amount = amount - serviceFee;Console.WriteLine(“No funds available for withdrawal!“);public override void PayInterest()/ No interest is paidprivate void StateChangeCheck()if (balance upperLimit)account.State = new Si
7、lverState(this);/ “ConcreteState“/ Silver is non-interest bearing stateclass SilverState : State/ Overloaded constructorspublic SilverState(State state) :this( state.Balance, state.Account) public SilverState(double balance, Account account)this.balance = balance;this.account = account;Initialize();
8、private void Initialize()/ Should come from a datasourceinterest = 0.0;lowerLimit = 0.0;upperLimit = 1000.0;public override void Deposit(double amount)balance += amount;StateChangeCheck();public override void Withdraw(double amount)balance -= amount;StateChangeCheck();public override void PayInteres
9、t()balance += interest * balance;StateChangeCheck();private void StateChangeCheck()if (balance upperLimit)account.State = new GoldState(this);/ “ConcreteState“/ Interest bearing stateclass GoldState : State/ Overloaded constructorspublic GoldState(State state): this(state.Balance,state.Account) publ
10、ic GoldState(double balance, Account account)this.balance = balance;this.account = account;Initialize();private void Initialize()/ Should come from a databaseinterest = 0.05;lowerLimit = 1000.0;upperLimit = 10000000.0;public override void Deposit(double amount)balance += amount;StateChangeCheck();pu
11、blic override void Withdraw(double amount)balance -= amount;StateChangeCheck();public override void PayInterest()balance += interest * balance;StateChangeCheck();private void StateChangeCheck()if (balance 0.0)account.State = new RedState(this);else if (balance lowerLimit)account.State = new SilverSt
12、ate(this);/ “Context“class Accountprivate State state;private string owner;/ Constructorpublic Account(string owner)/ New accounts are Silver by defaultthis.owner = owner;state = new SilverState(0.0, this);/ Propertiespublic double Balanceget return state.Balance; public State Stateget return state;
13、 set state = value; public void Deposit(double amount)state.Deposit(amount);Console.WriteLine(“Deposited 0:C - “, amount);Console.WriteLine(“ Balance = 0:C“, this.Balance);Console.WriteLine(“ Status = 0n“ ,this.State.GetType().Name);Console.WriteLine(“);public void Withdraw(double amount)state.Withd
14、raw(amount);Console.WriteLine(“Withdrew 0:C - “, amount);Console.WriteLine(“ Balance = 0:C“, this.Balance);Console.WriteLine(“ Status = 0n“ ,this.State.GetType().Name);public void PayInterest()state.PayInterest();Console.WriteLine(“Interest Paid - “);Console.WriteLine(“ Balance = 0:C“, this.Balance)
15、;Console.WriteLine(“ Status = 0n“ ,this.State.GetType().Name);结果:State 模式的几个要点:1.State 模式将所有一个特定状态相关的行为都放入一个 State 的子类对象中,在对象状态切换时,切换相应的对象;但同时维持 State 的接口,这样实现了具体操作与状态转换之间的解耦。2.为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的-即要么彻底转换过来,要么不转换。3.如果 State 对象没有实例变量,那么各个上下文可以共享 同一个 State 对象,从而节省对象开销。