文章目录
1.状态模式定义
1.1 定义
允许一个对象在其内部状态改变时自动改变其行为,对象看起来就像是改变了它的类
1.2 解决的问题
每个对象都有其对应的状态,而每个状态又对应一些相应的行为,如果某个对象有多个状态时,那么就会对应很多的行为。那么对这些状态的判断和根据状态完成的行为,就会导致多重条件语句,并且如果添加一种新的状态时,需要更改之前现有的代码。这样的设计显然违背了开闭原则。状态模式正是用来解决这样的问题的。状态模式将每种状态对应的行为抽象出来成为单独新的对象,这样状态的变化不再依赖于对象内部的行为。
2.UML类图
本文以一个银行卡会员升降级的例子解释状态模式
3.状态模式实现
3.1 State
public abstract class State
{
// Properties
public Account? Account { get; set; }
// Method
public abstract void Deposit(double amount); // 存钱
public abstract void Withdraw(double amount); // 取钱
}
3.2 Copper 铜卡
// 铜卡
public class Copper : State
{
public static double LowerLimit = 100.00; // 账户升降级下限
private Account? account;
public Copper(Account account)
{
this.account = account;
}
public override void Deposit(double amount)
{
if (amount < 0) return;
account!.Balance += amount;
StateChangeCheck();
}
public override void Withdraw(double amount)
{
if (amount <= 0)
Console.WriteLine("请输入正确取款金额");
if (account!.Balance - amount < 0)
{
Console.WriteLine($"钱不够啦!!!余额:{account.Balance},你要取:{amount}");
return;
}
account.Balance -= amount;
StateChangeCheck();
}
private void StateChangeCheck()
{
if (account!.Balance >= GoldState.LowerLimit) // 升级成金卡
account.State = new GoldState(account);
else if (account!.Balance >= SilverState.LowerLimit) // 升级成银卡
account.State = new SilverState(account);
}
}
3.3 SilverState 银卡
public class SilverState : State
{
public static double LowerLimit = 1000.00; // 账户升降级下限
private Account? account;
public SilverState(Account account)
{
this.account = account;
}
// 存钱
public override void Deposit(double amount)
{
if (amount < 0) return;
account!.Balance += amount;
StateChangeCheck();
}
// 取钱
public override void Withdraw(double amount)
{
if (amount <= 0)
Console.WriteLine("请输入正确取款金额");
if (account!.Balance - amount < 0)
{
Console.WriteLine($"钱不够啦!!!余额:{account.Balance},你要取:{amount}");
return;
}
account.Balance -= amount;
StateChangeCheck();
}
private void StateChangeCheck()
{
if (account!.Balance >= GoldState.LowerLimit) // 升级成金卡
account.State = new GoldState(account);
else if (account!.Balance <= SilverState.LowerLimit) // 降级成铜卡
account.State = new Copper(account);
}
}
3.4 GoldState 金卡
public class GoldState : State
{
public static double LowerLimit = 10000.00; // 账户升降级下限
private Account? account;
public GoldState(Account account)
{
this.account = account;
}
// 存钱
public override void Deposit(double amount)
{
if (amount < 0) return;
account!.Balance += amount;
StateChangeCheck();
}
// 取钱
public override void Withdraw(double amount)
{
if (amount <= 0)
Console.WriteLine("请输入正确取款金额");
if (account!.Balance - amount < 0)
{
Console.WriteLine($"钱不够啦!!!余额:{account.Balance},你要取:{amount}");
return;
}
account.Balance -= amount;
StateChangeCheck();
}
private void StateChangeCheck()
{
if (account!.Balance <= SilverState.LowerLimit) // 降级成铜卡
account.State = new Copper(account);
else if (account!.Balance <= GoldState.LowerLimit) // 降级成银卡
account.State = new SilverState(account);
}
}
3.5 Account 账户
public class Account
{
public State State { get; set; }
public string Owner { get; set; }
public double Balance { get; set; } // 余额
public Account(string owner)
{
this.Owner = owner;
this.State = new Copper(this);
}
public void Deposit(double amount)
{
State.Deposit(amount);
Console.WriteLine($"存款金额为:¥{amount}");
Console.WriteLine($"账户余额为:¥{this.Balance}");
Console.WriteLine($"账户状态为: {this.State.GetType().Name}");
Console.WriteLine();
}
public void Withdraw(double amount)
{
State.Withdraw(amount);
Console.WriteLine($"取款金额为:¥{amount}");
Console.WriteLine($"账户余额为:¥{this.Balance}");
Console.WriteLine($"账户状态为: {this.State.GetType().Name}");
Console.WriteLine();
}
}
4.使用示例
Console.WriteLine("----------------------- 状态模式 ----------------------------");
Account account = new Account("ming");
account.Withdraw(100);
account.Deposit(10.5);
account.Deposit(1000.5);
account.Withdraw(10000);
account.Withdraw(1000.5);
account.Deposit(10000.1);
account.Withdraw(5000);
结果:
----------------------- 状态模式 ----------------------------
钱不够啦!!!余额:0,你要取:100
取款金额为:¥100
账户余额为:¥0
账户状态为: Copper
存款金额为:¥10.5
账户余额为:¥10.5
账户状态为: Copper
存款金额为:¥1000.5
账户余额为:¥1011
账户状态为: SilverState
钱不够啦!!!余额:1011,你要取:10000
取款金额为:¥10000
账户余额为:¥1011
账户状态为: SilverState
取款金额为:¥1000.5
账户余额为:¥10.5
账户状态为: Copper
存款金额为:¥10000.1
账户余额为:¥10010.6
账户状态为: GoldState
取款金额为:¥5000
账户余额为:¥5010.6
账户状态为: SilverState
5.状态模式应用场景
在以下情况下可以考虑使用状态者模式:
- 当一个对象状态转换的条件表达式过于复杂时可以使用状态者模式。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。
- 当一个对象行为取决于它的状态,并且它需要在运行时刻根据状态改变它的行为时,就可以考虑使用状态者模式。
6.状态模式优缺点
状态者模式的主要优点是:
- 将状态判断逻辑每个状态类里面,可以简化判断的逻辑。
- 当有新的状态出现时,可以通过添加新的状态类来进行扩展,扩展性好。
状态者模式的主要缺点是:
- 如果状态过多的话,会导致有非常多的状态类,加大了开销。