Концептуальный пример Государственного проектного шаблона в C# - PullRequest
1 голос
/ 30 мая 2020

В настоящее время я изучаю паттерн государственного проектирования и думаю, что мне довольно понятно, как он работает. Я рассматривал концептуальный пример, который я опубликовал ниже. Есть только одна часть кода, которую я не совсем понимаю.

using System;

namespace BranchingDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.ReadLine();
        }


    }
    // State Interface
    interface IAccountState
    {
        IAccountState Deposit(Action addToBalance);
        IAccountState Withdraw(Action subtractFromBalance);
        IAccountState Freeze();
        IAccountState HolderVerified();
        IAccountState Close();
    }

    //Context
    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();
        }

    }
    //Concrete State
    class Active : IAccountState
    {
        private Action OnUnfreeze { get; }

        public Active(Action onUnfreeze)
        {
            this.OnUnfreeze = onUnfreeze;
        }

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

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

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

    //Concrete State

    class Closed : IAccountState
    {
        public IAccountState Deposit(Action addToBalance) => this;
        public IAccountState Withdraw(Action subtractFromBalance) => this;
        public IAccountState Freeze() => this;
        public IAccountState HolderVerified() => this;
        public IAccountState Close() => this;
    }
}

В конкретном классе Active есть свойство типа делегат действия, которое передается как параметр в его конструкторе. Также в конструкторе класса контекста в качестве параметра передается делегат действия типа. Теперь концептуально я понимаю, что это делается, поскольку это обеспечивает обратную ссылку на объект контекста (учетную запись) с состоянием, то есть закрытым или активным. Эта обратная ссылка может использоваться Состояниями для перехода контекста в другое Состояние. Мой первый вопрос: почему использовался делегат?

Однако я пытался запустить код и отладить его, чтобы проиллюстрировать, что происходит. Поэтому мой вопрос в коде: как мне инициализировать новую учетную запись? Аккаунты начинаются с состояния NotVerified. Я пробовал этот код.

Action initialState = () => { };
            Account account= new Account(initialState);

Если я затем хочу определить состояние учетной записи, как мне это закодировать?

1 Ответ

0 голосов
/ 01 июня 2020

Мне удалось получить подробную информацию о состоянии, сделав атрибут State в классе Account publi c. Затем в программном классе я мог бы выполнить следующее:

Action initialState = () => { };
Account testAccount= new Account(initialState,0);
var currentState = testAccount.State;
Console.WriteLine(currentState.GetType().Name);
testAccount.HolderVerified();
currentState = testAccount.State;
Console.WriteLine(currentState.GetType().Name);
testAccount.Deposit(12);
currentState = testAccount.State;
Console.WriteLine(currentState.GetType().Name + $" Balance: {testAccount.Balance}");
testAccount.Close();
currentState = testAccount.State;
Console.WriteLine(currentState.GetType().Name);
Console.ReadLine();

Я также изменил конструктор Account, чтобы взять и начальную сумму для баланса.

...