1. 定义
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。2. UML 类图
3. 结构代码
// State pattern -- Structural example
|
using System;
namespace DoFactory.GangOfFour.State.Structural { ///<summary> /// MainApp startup class for Structural /// State Design Pattern. ///</summary> classMainApp { ///<summary> /// Entry point into console application. ///</summary> staticvoid Main() { // Setup context in a state Context c =new Context(newConcreteStateA());
// Issue requests, which toggles state c.Request(); c.Request(); c.Request(); c.Request();
// Wait for user Console.ReadKey(); } }
///<summary> /// The 'State' abstract class ///</summary> abstractclass State { publicabstract void Handle(Context context); }
///<summary> /// A 'ConcreteState' class ///</summary> classConcreteStateA : State { publicoverride void Handle(Context context) { context.State = new ConcreteStateB(); } }
///<summary> /// A 'ConcreteState' class ///</summary> classConcreteStateB : State { publicoverride void Handle(Context context) { context.State = new ConcreteStateA(); } }
///<summary> /// The 'Context' class ///</summary> classContext { privateState _state;
// Constructor public Context(State state) { this.State = state; }
// Gets or sets the state publicState State { get {return _state; } set { _state = value; Console.WriteLine("State: " + _state.GetType().Name); } }
publicvoid Request() { _state.Handle(this); } } } |
Output
State: ConcreteStateA
State: ConcreteStateB State: ConcreteStateA State: ConcreteStateB State: ConcreteStateA |
4. 实例代码
// State pattern -- Real World example
|
using System;
namespace DoFactory.GangOfFour.State.RealWorld { ///<summary> /// MainApp startup class for Real-World /// State Design Pattern. ///</summary> classMainApp { ///<summary> /// Entry point into console application. ///</summary> staticvoid Main() { // Open a new account Account account =new Account("Jim Johnson");
// Apply financial transactions account.Deposit(500.0); account.Deposit(300.0); account.Deposit(550.0); account.PayInterest(); account.Withdraw(2000.00); account.Withdraw(1100.00);
// Wait for user Console.ReadKey(); } }
///<summary> /// The 'State' abstract class ///</summary> abstractclass State { protectedAccount account; protecteddouble balance;
protecteddouble interest; protecteddouble lowerLimit; protecteddouble upperLimit;
// Properties publicAccount Account { get {return account; } set { account =value; } }
publicdouble Balance { get {return balance; } set { balance =value; } }
publicabstract void Deposit(double amount); publicabstract void Withdraw(double amount); publicabstract void PayInterest(); }
///<summary> /// A 'ConcreteState' class ///<remarks> /// Red indicates that account is overdrawn ///</remarks> ///</summary> classRedState : State { privatedouble _serviceFee;
// Constructor public RedState(State state) { this.balance = state.Balance; this.account = state.Account; Initialize(); }
privatevoid Initialize() { // Should come from a datasource interest = 0.0; lowerLimit = -100.0; upperLimit = 0.0; _serviceFee = 15.00; }
publicoverride void Deposit(double amount) { balance += amount; StateChangeCheck(); }
publicoverride void Withdraw(double amount) { amount = amount - _serviceFee; Console.WriteLine("No funds available for withdrawal!"); }
publicoverride void PayInterest() { // No interest is paid }
privatevoid StateChangeCheck() { if (balance > upperLimit) { account.State = new SilverState(this); } } }
///<summary> /// A 'ConcreteState' class ///<remarks> /// Silver indicates a non-interest bearing state ///</remarks> ///</summary> classSilverState : State { // Overloaded constructors
public SilverState(State state) : this(state.Balance, state.Account) { }
public SilverState(double balance,Account account) { this.balance = balance; this.account = account; Initialize(); }
privatevoid Initialize() { // Should come from a datasource interest = 0.0; lowerLimit = 0.0; upperLimit = 1000.0; }
publicoverride void Deposit(double amount) { balance += amount; StateChangeCheck(); }
publicoverride void Withdraw(double amount) { balance -= amount; StateChangeCheck(); }
publicoverride void PayInterest() { balance += interest * balance; StateChangeCheck(); }
privatevoid StateChangeCheck() { if (balance < lowerLimit) { account.State = new RedState(this); } elseif (balance > upperLimit) { account.State = new GoldState(this); } } }
///<summary> /// A 'ConcreteState' class ///<remarks> /// Gold indicates an interest bearing state ///</remarks> ///</summary> classGoldState : State { // Overloaded constructors public GoldState(State state) : this(state.Balance, state.Account) { }
public GoldState(double balance,Account account) { this.balance = balance; this.account = account; Initialize(); }
privatevoid Initialize() { // Should come from a database interest = 0.05; lowerLimit = 1000.0; upperLimit = 10000000.0; }
publicoverride void Deposit(double amount) { balance += amount; StateChangeCheck(); }
publicoverride void Withdraw(double amount) { balance -= amount; StateChangeCheck(); }
publicoverride void PayInterest() { balance += interest * balance; StateChangeCheck(); }
privatevoid StateChangeCheck() { if (balance < 0.0) { account.State = new RedState(this); } elseif (balance < lowerLimit) { account.State = new SilverState(this); } } }
///<summary> /// The 'Context' class ///</summary> classAccount { privateState _state; privatestring _owner;
// Constructor public Account(string owner) { // New accounts are 'Silver' by default this._owner = owner; this._state =new SilverState(0.0,this); }
// Properties publicdouble Balance { get {return _state.Balance; } }
publicState State { get {return _state; } set { _state =value; } }
publicvoid Deposit(double amount) { _state.Deposit(amount); Console.WriteLine("Deposited {0:C} --- ", amount); Console.WriteLine(" Balance = {0:C}",this.Balance); Console.WriteLine(" Status = {0}", this.State.GetType().Name); Console.WriteLine(""); }
publicvoid Withdraw(double amount) { _state.Withdraw(amount); Console.WriteLine("Withdrew {0:C} --- ", amount); Console.WriteLine(" Balance = {0:C}",this.Balance); Console.WriteLine(" Status = {0}\n", this.State.GetType().Name); }
publicvoid PayInterest() { _state.PayInterest(); Console.WriteLine("Interest Paid --- "); Console.WriteLine(" Balance = {0:C}",this.Balance); Console.WriteLine(" Status = {0}\n", this.State.GetType().Name); } } } |
Output
Deposited $500.00 ---
Balance = $500.00 Status = SilverState Deposited $300.00 --- Balance = $800.00 Status = SilverState Deposited $550.00 --- Balance = $1,350.00 Status = GoldState Interest Paid --- Balance = $1,417.50 Status = GoldState Withdrew $2,000.00 --- Balance = ($582.50) Status = RedState No funds available for withdrawal! Withdrew $1,100.00 --- Balance = ($582.50) Status = RedState |
该文章来自:http://www.dofactory.com/Patterns/PatternState.aspx