状态者模式介绍
状态者模式:
- 当一个类中有多个状态时,每个状态对应着不同的行为。那么对这些状态的判断和根据状态完成的行为,就会导致多重条件语句,并且如果添加一种新的状态时,需要更改之前现有的代码。这样的设计显然违背了开闭原则。状态模式正是用来解决这样的问题的。
- 状态者模式是对对象状态的抽象,从而把对象中对状态复杂的判断逻辑已到各个状态类里面,从而简化逻辑判断。
状态者模式的组成: 1.抽象的状态类 2.状态类的具体实现 3.使用状态的对象
例子
- 打篮球的时候运动员可以有正常状态、不正常状态和超常状态。
- 曾侯乙编钟中,’钟是抽象接口’,’钟A’等是具体状态,’曾侯乙编钟’是具体环境(Context)。
- 银行账户根据余额可分为RedState、SilverState和GoldState。这些状态分别代表透支账号,新开账户和标准账户。账号余额在【-100.0,0.0】范围表示处于RedState状态,账号余额在【0.0 , 1000.0】范围表示处于SilverState,账号在【1000.0, 100000.0】范围表示处于GoldState状态。下面以这样的一个场景实现下状态者模式,具体实现代码如下所示:
下面,就以银行账户的状态来实现下状态者模式。
状态者模式UML图
状态者模式的实现
Account(账户类,包含账户状态和账户的用户名):
using System;
namespace cchoop.StatePattern
{
class Account
{
public State MyState { get; set; }
public string Owner { get; set; }
public Account(string owner)
{
this.Owner = owner;
//默认状态为新开账户的状态
this.MyState = new SilverState(0.00f, this);
}
//存钱
public void Deposit(float amount)
{
MyState.Deposit(amount);
Console.WriteLine("存款金额为:" + amount);
Console.WriteLine("账户本息总金额为:" + MyState.Balance);
Console.WriteLine("账户状态为:" + MyState.GetType().Name);
Console.WriteLine("=======================================");
}
//取钱
public void WithDraw(float amount)
{
MyState.WithDraw(amount);
Console.WriteLine("取款金额为:" + amount);
Console.WriteLine("账户本息总金额为:" + MyState.Balance);
Console.WriteLine("账户状态为:" + MyState.GetType().Name);
Console.WriteLine("=======================================");
}
//获取利息
public void PayInterest()
{
MyState.PayInterest();
Console.WriteLine("账户余额为:" + MyState.Balance);
Console.WriteLine("账户状态为:" + MyState.GetType().Name);
Console.WriteLine("=======================================");
}
}
}
State(账户的状态抽象类,所有具体的状态类必须继承自该类):
using System;
namespace cchoop.StatePattern
{
abstract class State
{
public Account Account { get; set; }
public float Balance { get; set; } //余额
public float Interest { get; set; } //利率
public float LowerLimit { get; set; } //下限
public float UpperLimit { get; set; } //上限
public abstract void Deposit(float amount); //存款
public abstract void WithDraw(float amount); //取钱
public abstract void PayInterest(); //获得的利息
public abstract void CheckState(); //检查状态,进行状态的切换
}
}
RedState(透支状态):
using System;
namespace cchoop.StatePattern
{
/// <summary>
/// 账户透支状态,账号余额在【-100.0,0.0】范围
/// </summary>
class RedState:State
{
public RedState(State state)
{
this.Balance = state.Balance;
this.Account = state.Account;
this.Interest = 0.00f;
this.LowerLimit = -100.0f;
this.UpperLimit = 0.0f;
}
public override void Deposit(float amount)
{
this.Balance += amount;
CheckState();
}
public override void WithDraw(float amount)
{
Console.WriteLine("账户已经透支,没有钱可以取了喔!");
}
public override void PayInterest()
{
Console.WriteLine("账户已经透支,没有利息的!");
}
public override void CheckState()
{
if (this.Balance > this.UpperLimit)
{
Account.MyState = new SilverState(this);
}
}
}
}
SilverState(新开户状态):
using System;
namespace cchoop.StatePattern
{
class SilverState:State
{
/// <summary>
/// 账户新开户状态,余额在【0.0 , 1000.0】范围
/// </summary>
public SilverState(State state)
: this(state.Balance, state.Account)
{
}
public SilverState(float balance, Account account)
{
this.Balance = balance;
this.Account = account;
this.Interest = 0.01f;
this.LowerLimit = 0.0f;
this.UpperLimit = 1000.0f;
}
public override void Deposit(float amount)
{
this.Balance += amount;
CheckState();
}
public override void WithDraw(float amount)
{
this.Balance -= amount;
CheckState();
}
public override void PayInterest()
{
this.Balance += this.Balance * this.Interest;
CheckState();
}
public override void CheckState()
{
if (this.Balance > this.UpperLimit)
{
Account.MyState = new GoldState(this);
}
else if (this.Balance < this.LowerLimit)
{
Account.MyState = new RedState(this);
}
}
}
}
GoldState(标准状态):
using System;
namespace cchoop.StatePattern
{
/// <summary>
/// 账户标准状态,账号在【1000.0, 100000.0】范围
/// </summary>
class GoldState : State
{
public GoldState(State state)
{
this.Balance = state.Balance;
this.Account = state.Account;
this.Interest = 0.05f;
this.LowerLimit = 1000.0f;
this.UpperLimit = 100000.0f;
}
public override void Deposit(float amount)
{
this.Balance += amount;
CheckState();
}
public override void WithDraw(float amount)
{
this.Balance -= amount;
CheckState();
}
public override void PayInterest()
{
this.Balance += this.Balance * this.Interest;
CheckState();
}
public override void CheckState()
{
if (this.Balance < 0.0f)
{
Account.MyState = new RedState(this);
}
else if (this.Balance < this.LowerLimit)
{
Account.MyState = new SilverState(this);
}
}
}
}
Customer(测试):
using System;
namespace cchoop.StatePattern
{
class Customer
{
static void Main(string[] args)
{
Account account = new Account("cchoop");
account.Deposit(200);
account.WithDraw(500);
account.WithDraw(500);
}
}
}