现在的位置: 首页 > 综合 > 正文

状态模式(State)

2013年08月24日 ⁄ 综合 ⁄ 共 7493字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.