dimanche 24 novembre 2019

How to correctly implement State Pattern?

  1. An Account could have various states such as Frozen, Active, NotVerified, Closed.
  2. And Account could perform following actions: Deposit(), Withdraw(), HolderVerified(), Close(), Freeze()
  3. These implementation of these actions could vary depending on current state of the account.

Below is my way of tackling the above scenario. However, what if we have a situation where we have to :

Deduct 10 percent of the deposit when the deposit is made when current state of the account is Frozen?

ACCOUNT

    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();

    }

Concrete Implementation of IAccountState

ACTIVE

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();

}

NOTVERIFIED

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;
    }

How will you deal with the situation when you have to deduct 10 percent of the deposit when current state of the account is Frozen?

I am not sure how to modify Deposit method in NotVerified class to meet the requirement :

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

Aucun commentaire:

Enregistrer un commentaire