首页 > 解决方案 > 如何正确实现状态模式?

问题描述

  1. 一个帐户可以有各种状态,例如 Frozen、Active、NotVerified、Closed。
  2. Account 可以执行以下操作:Deposit()、Withdraw()、HolderVerified()、Close()、Freeze()
  3. 这些操作的这些实施可能会因帐户的当前状态而异。

以下是我处理上述情况的方法。但是,如果我们遇到必须:

账户当前状态为冻结状态下入金,扣10%入金?

帐户

    class Account
    {
        public decimal Balance { get; private set; }

        private IAccountState State { get; set; }

        public Account(Action onUnfreeze)
        {
            this.State = new NotVerified(onUnfreeze);
        }

        public void Deposit(decimal amount)
        {
            this.State = this.State.Deposit(() => { this.Balance += amount; });
        }

        public void Withdraw(decimal amount)
        {
            this.State = this.State.Withdraw(() => { this.Balance -= amount; });
        }

        public void HolderVerified()
        {
            this.State = this.State.HolderVerified();
        }

        public void Close()
        {
            this.State = this.State.Close();
        }

        public void Freeze()
        {
            this.State = this.State.Freeze();
        }
    }

IAccountState

interface IAccountState
    {
        IAccountState Deposit(Action addToBalance);
        IAccountState Withdraw(Action substractFromBalance);
        IAccountState Freeze();
        IAccountState HolderVerified();
        IAccountState Close();

    }

IAccountState 的具体实现

积极的

class Active : IAccountState
    {
        private Action OnUnfreeze { get; }
        public Active(Action onUnfreeze)
        {
            OnUnfreeze = onUnfreeze;
        }



        public IAccountState Deposit(Action addToBalance)
        {
            addToBalance();
            return this;
        }

    public IAccountState Withdraw(Action substractFromBalance)
    {
        substractFromBalance();
        return this;
    }

    public IAccountState HolderVerified() => this;
    public IAccountState Freeze() => new Frozen(this.OnUnfreeze);
    public IAccountState Close() => new Closed();
}

未验证

class NotVerified : IAccountState
    {
        public Action OnUnfreeze { get; }
        public NotVerified(Action onUnfreeze)
        {
            this.OnUnfreeze = onUnfreeze;
        }
        public IAccountState Close() => new Closed();

        public IAccountState Deposit(Action addToBalance)
        {
            addToBalance();
            return this;
        }

        public IAccountState Freeze() => this;

        public IAccountState HolderVerified() => new Active(this.OnUnfreeze);

        public IAccountState Withdraw(Action substractFromBalance) => this;
    }

当账户的当前状态为冻结时,当您必须扣除 10% 的存款时,您将如何处理?

我不确定如何修改 NotVerified 类中的 Deposit 方法以满足要求:

 public IAccountState Deposit(Action addToBalance)
 {
    addToBalance();
    return this;
 }

标签: c#.netoopdesign-patternsobject-oriented-analysis

解决方案


我会使用枚举而不是接口:

enum AccountState
{
    NotVerified,
    Active,
    Frozen,
    Closed
}

class Account
{
    public decimal Balance { get; private set; }

    // I assumed the bank would want to deposit the 10% to its own account        
    public decimal Fees { get; set; }

    public AccountState state {get; private set; } = AccountState.NotVerified;

    public Account() {}

    public void Deposit(decimal amount) {
        if (this.state == AccountState.Active)
            this.Balance += amount;
        else if (this.state == AccountState.Frozen)
        {
            this.Balance += amount * (decimal).9;
            this.Fees += amount * (decimal).1;
        }
    }

    public void Withdraw(decimal amount) {
        if (this.state == AccountState.Active)
            this.Balance -= amount;
    }

    public bool HolderVerified() {
        return (this.state == AccountState.Active);
    }

    public void Close() {
        this.state = AccountState.Closed;
    }

    public void Freeze() {
        this.state = AccountState.Frozen;
    }
}

推荐阅读