二十三.行为型设计模式——State Pattern(状态模式)

  • 定义

  当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

  UML类图如下:  

  

  其中类和对象的关系为:

  1.Context(情景类):定义客户应用程序有兴趣的接口;维护一个ConcreteState(具体状态)子类的实例对象。

  2.State(抽象状态类):定义一个接口以封装与Context的一个特别状态(State)相关的行为。

  3.ConcreteState(具体状态类):每一个具体状态类(ConcreteState)实现了一个Context的状态(state)相关的行为。

  典型应用的顺序图如下:  

  

  • 实例1——账户分类:

    允许账户因它的余额不同而有不同的分类,分为RedState(红色状态)、SilverState(银色状态)、GoldState(金色状态)。这些状态表示了账户是否透支、新账户或常务账户(信誉好)。
类图如下:

  

 
    //抽象状态类
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; }
}
abstract public void Initialize();
abstract public void Deposit(double amount);
abstract public void Withdraw(double amount);
abstract public void PayInterest();
abstract public void StateChangeCheck();
}

//具体状态——透支账户(红色账户)
class RedState : State
{
double servuceFee;
//构造函数,由其他状态对象传值过来
public RedState(State state)
{
this.balance = state.Balance;
this.account = state.Account;
Initialize();
}
public override void Initialize()
{
interest = 0.0;
lowerLimit = -100.0;
upperLimit = 0.0;
servuceFee = 15.00;
}
public override void Deposit(double amount)
{
balance += amount;
StateChangeCheck();
}
public override void Withdraw(double amount)
{
amount = amount - servuceFee;
Console.WriteLine("没有存款可供支取,支取失败");
}
public override void PayInterest()
{
//没有存款,银行不会支付利息
}
public override void StateChangeCheck()
{
if (balance > upperLimit)//当有存款,状态变为银色
account.State = new SilverState(this);
}
}

//具体状态——普通账户(银色账户)
class SilverState : State
{
//构造函数,由其他状态对象传值过来
public SilverState(double balance, Account account)
{
this.balance = balance;
this.account = account;
Initialize();
}
public SilverState(State state)
{
this.balance = state.Balance;
this.account = state.Account;
Initialize();
}
public override void Initialize()
{
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();
}
public override void StateChangeCheck()
{
if (balance < lowerLimit)
account.State = new RedState(this);
else if (balance > upperLimit)
account.State = new GoldState(this);
}
}

//具体状态——富裕账户(金色账户)
class GoldState : State
{
//构造函数,由其他状态对象传值过来
public GoldState(double balance, Account account)
{
this.balance = balance;
this.account = account;
Initialize();
}
public GoldState(State state)
{
this.balance = state.Balance;
this.account = state.Account;
Initialize();
}
public override void Initialize()
{
interest = 0.05;
lowerLimit = 1000.0;
upperLimit = 1000000.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();
}
public override void StateChangeCheck()
{
if (balance < 0.0)
account.State = new RedState(this);
else if (balance < lowerLimit)
account.State = new SilverState(this);
}
}

class Account
{
private State state;
private string owner;
public Account(string owner)
{
this.owner = owner;
state = new SilverState(0.0, this);
}
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:C}", this.state);
Console.WriteLine("");
}
public void Withdraw(double amount)
{
state.Withdraw(amount);
Console.WriteLine("取出{0:C}——", amount);
Console.WriteLine("现存金额={0:C}", this.Balance);
Console.WriteLine("状态={0:C}", this.state);
Console.WriteLine("");
}
public void PayInterest()
{
state.PayInterest();
Console.WriteLine("银行支付利息——");
Console.WriteLine("现存金额={0:C}", this.Balance);
Console.WriteLine("状态={0:C}", this.state);
Console.WriteLine("");
}
}
class Program
{
static void Main(string[] args)
{
Account account = new Account("张三");
account.Deposit(500.0);
account.Deposit(300.0);
account.Deposit(600.0);
account.PayInterest();
account.Withdraw(2000.0);
account.Withdraw(1000.0);
Console.Read();
}
}
 
  • 优势和缺陷

  状态模式在对象内保存特定的状态并且就不同的状态履行不同的行为,它使状态的变化显得清晰明了,也很容易创建对象的新状态。

  状态模式在工作流或游戏等各种系统中大量使用,例如在政府OA系统中,一个批文的状态有多种:未办、正在处理、正在批示、正在审核和已经完成等各种状态。在网络游戏中,一个游戏活动存在开始、开玩、正在玩、输赢等各种状态。使用状态模式就可以实现游戏状态的总控,而游戏状态决定了游戏的各个方面。

  • 应用情景

  下面的情景很适合应用状态模式:

  1.对象的行为依赖于它的状态并且它必须可以根据它的状态而改变它的行为。

  2.操作很多部分都带有与对象状态有关的大量条件语句。

posted on 2011-11-22 00:09  tLEE  阅读(508)  评论(0编辑  收藏  举报

导航