State Pattern(状态模式)
state pattern
- 状态模式:状态模式一般用来实现状态机。状态机常用在游戏、工作流引擎等开发中。
- 有限状态机(Finite-State Machine)FSM,有三个组成部分:状态(state)、事件(Event)、动作(Action)。事件也被称为转移条件(Transition Condition)。事件触发状态的转移,可能触发动作执行,也可不触发动作执行。
State Pattern 角色分析
- Context: 环境类又称上下文类,它是拥有状态的对象,在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象,可以定义初始状态;
- State: 抽象状态类,用于定义一个接口以封装与环境类的一个特定状态相关的行为;
- ConcreteState: 具体状态类是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。
- 适用场景:
State Pattern在工作流或游戏等类型的软件中得以广泛使用,甚至可以用于这些系统的核心功能设计,如在政府OA办公系统中,一个批文的状态有多种:尚未办理;正在办理;正在批示;正在审核;已经完成等各种状态,而且批文状态不同时对批文的操作也有所差异。使用状态模式可以描述工作流对象(如批文)的状态转换以及不同状态下它所具有的行为。
代码示例
下面示例代码中,模拟context有两个状态,concreteStateA与ConcreteStateB,当context调用request()方法,触发concreteStateA转移为ConcreteStateB。
/*
*State Pattern
*
*/
using System;
using System.Collections.Generic;
namespace Pattern03
{
class Program
{
static void Main(string[] args)
{
//创建context,并初始化当前状态
Context c = new Context(new ConcreteStateA());
//事件触发状态转移
c.Request();
c.Request();
c.Request();
Console.ReadKey();
}
}
abstract class State
{
public abstract void Handle(Context context);
}
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
class Context
{
private State _state;//维护一个State对象
public Context(State state)
{
this._state = state;
}
public State State
{
get { return _state; }
set
{
_state = value;
Console.WriteLine("State: " + _state.GetType().Name);
}
}
public void Request()
{
_state.Handle(this);
}
}
}
示例2
示例代码状态转移图
/*
* State Pattern
*/
using System;
using System.Collections;
namespace Pattern02
{
class Program
{
static void Main(string[] args)
{
Account account = new Account("Jim Johnson");
account.Deposit(500.0);
account.Deposit(300.0);
account.Deposit(550.0);
account.PayInterest();
account.Withdraw(2000.00);
account.Withdraw(1100.00);
account.Deposit(2000.00);
Console.ReadLine();
}
}
/// <summary>
/// state
/// </summary>
abstract class State
{
protected Account account;
protected double balance;
protected double interest;
protected double lowerLimit;
protected double upperLimit;
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();
}
class RedState : State
{
private double _serviceFee;
public RedState(State state):
this(state.Account,state.Balance)
{ }
public RedState(Account account, double balance)
{
this.balance = balance;
this.account = 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("无可用余额!");
}
public override void PayInterest()
{
// No interest is paid
}
private void StateChangeCheck()
{
if (balance > upperLimit)
{
account.State = new SilverState(this);
}
}
}
class SilverState : State
{
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);
}
}
}
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>
/// 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("本次存款金额 {0:C} --- ", amount);
Console.WriteLine(" 当前余额 = {0:C}", this.Balance);
Console.WriteLine(" 账户状态 = {0}",
this.State.GetType().Name);
Console.WriteLine("");
}
public void Withdraw(double amount)
{
_state.Withdraw(amount);
Console.WriteLine("本次取款金额 {0:C} --- ", amount);
Console.WriteLine(" 当前余额 = {0:C}", this.Balance);
Console.WriteLine(" 账户状态 = {0}\n",
this.State.GetType().Name);
}
public void PayInterest()
{
_state.PayInterest();
Console.WriteLine(" 利息 --- ");
Console.WriteLine(" 当前余额 = {0:C}", this.Balance);
Console.WriteLine(" 账户状态 = {0}\n",
this.State.GetType().Name);
}
}
}
总结
状态模式,关键是搞清楚各状态之间的转移。也就是状态(state)、事件(Event)、动作(Action)之间事件触发的状态转移及动作执行。