设计模式24:State Pattern (状态模式)
英文原文:http://www.dofactory.com/Patterns/PatternState.aspx
一、State Pattern (状态模式)
Define: Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
定义:当一个对象的内部状态进行改变的时候允许对象改变其行为。这个对象将显然可以改变其类。
二、UML类图
- Context (Account)
- defines the interface of interest to clients
- maintains an instance of a ConcreteState subclass that defines the current state.
- State (State)
- defines an interface for encapsulating the behavior associated with a particular state of the Context.
- Concrete State (RedState, SilverState, GoldState)
- each subclass implements a behavior associated with a state of Context
三、State Pattern (状态模式)实例性代码
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace State_Pattern
- {
- /// <summary>
- /// MainApp startup class for Structural
- /// State Design Pattern.
- /// </summary>
- class MainApp
- {
- /// <summary>
- /// Entry point into console application.
- /// </summary>
- static void Main()
- {
- // Setup context in a state
- Context c = new Context(new ConcreteStateA());
- // Issue requests, which toggles state
- c.Request();
- c.Request();
- c.Request();
- c.Request();
- // Wait for user
- Console.ReadKey();
- }
- }
- /// <summary>
- /// The 'State' abstract class
- /// </summary>
- abstract class State
- {
- public abstract void Handle(Context context);
- }
- /// <summary>
- /// A 'ConcreteState' class
- /// </summary>
- class ConcreteStateA : State
- {
- public override void Handle(Context context)
- {
- context.State = new ConcreteStateB();
- }
- }
- /// <summary>
- /// A 'ConcreteState' class
- /// </summary>
- class ConcreteStateB : State
- {
- public override void Handle(Context context)
- {
- context.State = new ConcreteStateA();
- }
- }
- /// <summary>
- /// The 'Context' class
- /// </summary>
- class Context
- {
- private State _state;
- // Constructor
- public Context(State state)
- {
- this.State = state;
- }
- // Gets or sets the state
- public State State
- {
- get { return _state; }
- set
- {
- _state = value;
- Console.WriteLine("State: " +
- _state.GetType().Name);
- }
- }
- public void Request()
- {
- _state.Handle(this);
- }
- }
- }
四、使用State Pattern (状态模式)的实例代码
This real-world code demonstrates the State pattern which allows an Account to behave differently depending on its balance. The difference in behavior is delegated to State objects called RedState, SilverState and GoldState. These states represent overdrawn accounts, starter accounts, and accounts in good standing.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace State_Pattern
- {
- /// <summary>
- /// MainApp startup class for Real-World
- /// State Design Pattern.
- /// </summary>
- class MainApp
- {
- /// <summary>
- /// Entry point into console application.
- /// </summary>
- static void 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>
- abstract class State
- {
- protected Account account;
- protected double balance;
- protected double interest;
- protected double lowerLimit;
- protected double upperLimit;
- // Properties
- public Account Account
- {
- get { return account; }
- set { account = value; }
- }
- public double Balance
- {
- get { return balance; }
- set { balance = value; }
- }
- public abstract void Deposit(double amount);
- public abstract void Withdraw(double amount);
- public abstract void PayInterest();
- }
- /// <summary>
- /// A 'ConcreteState' class
- /// <remarks>
- /// Red indicates that account is overdrawn
- /// </remarks>
- /// </summary>
- class RedState : State
- {
- private double _serviceFee;
- // Constructor
- public RedState(State state)
- {
- this.balance = state.Balance;
- this.account = state.Account;
- Initialize();
- }
- private void Initialize()
- {
- // Should come from a datasource
- interest = 0.0;
- lowerLimit = -100.0;
- upperLimit = 0.0;
- _serviceFee = 15.00;
- }
- public override void Deposit(double amount)
- {
- 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 paid
- }
- private void StateChangeCheck()
- {
- if (balance > upperLimit)
- {
- account.State = new SilverState(this);
- }
- }
- }
- /// <summary>
- /// A 'ConcreteState' class
- /// <remarks>
- /// Silver indicates a non-interest bearing state
- /// </remarks>
- /// </summary>
- class SilverState : 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();
- }
- private void Initialize()
- {
- // Should come from a datasource
- interest = 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 PayInterest()
- {
- balance += interest * balance;
- StateChangeCheck();
- }
- private void StateChangeCheck()
- {
- if (balance < lowerLimit)
- {
- account.State = new RedState(this);
- }
- else if (balance > upperLimit)
- {
- account.State = new GoldState(this);
- }
- }
- }
- /// <summary>
- /// A 'ConcreteState' class
- /// <remarks>
- /// Gold indicates an interest bearing state
- /// </remarks>
- /// </summary>
- class GoldState : 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();
- }
- private void Initialize()
- {
- // Should come from a database
- interest = 0.05;
- lowerLimit = 1000.0;
- upperLimit = 10000000.0;
- }
- public override void Deposit(double amount)
- {
- balance += amount;
- StateChangeCheck();
- }
- public 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 SilverState(this);
- }
- }
- }
- /// <summary>
- /// The 'Context' class
- /// </summary>
- class Account
- {
- private State _state;
- private string _owner;
- // Constructor
- public Account(string owner)
- {
- // New accounts are 'Silver' by default
- this._owner = owner;
- this._state = new SilverState(0.0, this);
- }
- // Properties
- public double Balance
- {
- get { return _state.Balance; }
- }
- public State State
- {
- get { return _state; }
- 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 = {0}",
- this.State.GetType().Name);
- Console.WriteLine("");
- }
- public void 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);
- }
- public void PayInterest()
- {
- _state.PayInterest();
- Console.WriteLine("Interest Paid --- ");
- Console.WriteLine(" Balance = {0:C}", this.Balance);
- Console.WriteLine(" Status = {0}/n",
- this.State.GetType().Name);
- }
- }
- }
乐在其中设计模式(C#) - 状态模式(State Pattern)
介绍
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
示例
有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里。在对象内部可以根据用户的不同选择不同的数据持久化方案。
MessageModel
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.State
{
/// <summary>
/// Message实体类
/// </summary>
public class MessageModel
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="msg">Message内容</param>
/// <param name="pt">Message发布时间</param>
public MessageModel(string msg, DateTime pt)
{
this._message = msg;
this._publishTime = pt;
}
private string _message;
/// <summary>
/// Message内容
/// </summary>
public string Message
{
get { return _message; }
set { _message = value; }
}
private DateTime _publishTime;
/// <summary>
/// Message发布时间
/// </summary>
public DateTime PublishTime
{
get { return _publishTime; }
set { _publishTime = value; }
}
}
}
AbstractMessageState
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.State
{
/// <summary>
/// 状态模式抽象类
/// </summary>
public abstract class AbstractMessageState
{
/// <summary>
/// Context类型
/// </summary>
protected Message _message;
/// <summary>
/// Context类型属性
/// </summary>
public Message Message
{
get { return _message; }
set { _message = value; }
}
/// <summary>
/// 改变状态
/// </summary>
public abstract void StateChangeCheck();
/// <summary>
/// 获取Message
/// </summary>
/// <returns></returns>
public abstract List<MessageModel> Get();
/// <summary>
/// 插入Message
/// </summary>
/// <param name="mm">Message实体对象</param>
/// <returns></returns>
public abstract bool Insert(MessageModel mm);
}
}
XmlMessage
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.State
{
/// <summary>
/// Xml方式操作Message
/// </summary>
public class XmlMessage : AbstractMessageState
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message">Context类型参数</param>
public XmlMessage(Message message)
{
this._message = message;
}
/// <summary>
/// 改变状态
/// </summary>
public override void StateChangeCheck()
{
// 如果UserId是admin则变换状态为SqlMessage
if (this._message.UserId == "admin")
{
this._message.AbstractMessageState = new SqlMessage(this._message);
}
}
/// <summary>
/// 获取Message
/// </summary>
/// <returns></returns>
public override List<MessageModel> Get()
{
List<MessageModel> l = new List<MessageModel>();
l.Add(new MessageModel("XML方式获取Message", DateTime.Now));
return l;
}
/// <summary>
/// 插入Message
/// </summary>
/// <param name="mm">Message实体对象</param>
/// <returns></returns>
public override bool Insert(MessageModel mm)
{
// 代码略
return true;
}
}
}
SqlMessage
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.State
{
/// <summary>
/// Sql方式操作Message
/// </summary>
public class SqlMessage : AbstractMessageState
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="message">Context类型参数</param>
public SqlMessage(Message message)
{
this._message = message;
}
/// <summary>
/// 改变状态
/// </summary>
public override void StateChangeCheck()
{
}
/// <summary>
/// 获取Message
/// </summary>
/// <returns></returns>
public override List<MessageModel> Get()
{
List<MessageModel> l = new List<MessageModel>();
l.Add(new MessageModel("SQL方式获取Message", DateTime.Now));
return l;
}
/// <summary>
/// 插入Message
/// </summary>
/// <param name="mm">Message实体对象</param>
/// <returns></returns>
public override bool Insert(MessageModel mm)
{
// 代码略
return true;
}
}
}
Message
using System;
using System.Collections.Generic;
using System.Text;
namespace Pattern.State
{
/// <summary>
/// Context类
/// </summary>
public class Message
{
/// <summary>
/// 类型为状态模式抽象类的私有变量
/// </summary>
private AbstractMessageState _abstractMessageState;
/// <summary>
/// 类型为状态模式抽象类的属性
/// </summary>
public AbstractMessageState AbstractMessageState
{
get { return _abstractMessageState; }
set { _abstractMessageState = value; }
}
/// <summary>
/// UserId私有变量
/// </summary>
private string _userId;
/// <summary>
/// UserId
/// </summary>
public string UserId
{
get { return _userId; }
set { _userId = value; }
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="userId">UserId</param>
public Message(string userId)
{
this._userId = userId;
_abstractMessageState = new XmlMessage(this);
}
/// <summary>
/// 获取Message
/// </summary>
/// <returns></returns>
public List<MessageModel> Get()
{
// 修改状态
_abstractMessageState.StateChangeCheck();
return _abstractMessageState.Get();
}
/// <summary>
/// 插入Message
/// </summary>
/// <param name="mm">Message实体对象</param>
/// <returns></returns>
public bool Insert(MessageModel mm)
{
// 修改状态
_abstractMessageState.StateChangeCheck();
return _abstractMessageState.Insert(mm);
}
}
}
client
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Pattern.State;
public partial class State : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Message m = new Message("admin");
Response.Write(m.Insert(new MessageModel("插入", DateTime.Now)));
Response.Write("<br />");
Response.Write(m.Get()[0].Message + " " + m.Get()[0].PublishTime.ToString());
Response.Write("<br />");
m = new Message("user");
Response.Write(m.Insert(new MessageModel("插入", DateTime.Now)));
Response.Write("<br />");
Response.Write(m.Get()[0].Message + " " + m.Get()[0].PublishTime.ToString());
Response.Write("<br />");
}
}
运行结果
True
SQL方式获取Message 2007-3-6 22:58:17
True
XML方式获取Message 2007-3-6 22:58:17
参考
http://www.dofactory.com/Patterns/PatternState.aspx
OK
[源码下载]