状态模式(StatePattern)

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.状态模式优缺点

状态者模式的主要优点是:

  • 将状态判断逻辑每个状态类里面,可以简化判断的逻辑。
  • 当有新的状态出现时,可以通过添加新的状态类来进行扩展,扩展性好。

状态者模式的主要缺点是:

  • 如果状态过多的话,会导致有非常多的状态类,加大了开销。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值