Шаблон состояния и дизайн, управляемый предметной областью

Мы часто используем простые перечисления для представления состояния наших сущностей. Проблема возникает, когда мы вводим поведение, которое в значительной степени зависит от состояния или когда переходы между состояниями должны соответствовать определенным бизнес-правилам.

Возьмем следующий пример (, в котором для представления состояния используется перечисление.):

public class Vacancy {

    private VacancyState currentState;

    public void Approve() {
        if (CanBeApproved()) {
            currentState.Approve();
        }
    }

    public bool CanBeApproved() {
        return currentState == VacancyState.Unapproved
            || currentState == VacancyState.Removed
    }

    private enum VacancyState {
        Unapproved,
        Approved,
        Rejected,
        Completed,
        Removed
    }
}

Вы можете видеть, что этот класс скоро станет довольно многословным, поскольку мы добавим методы для Reject, Complete, Remove и т. д.

Вместо этого мы можем ввести шаблон состояния, который позволяет нам инкапсулировать каждое состояние как объект :

public abstract class VacancyState {

    protected Vacancy vacancy;

    public VacancyState(Vacancy vacancy) {
        this.vacancy = vacancy;
    }

    public abstract void Approve(); 
    // public abstract void Unapprove();
    // public abstract void Reject();
    // etc.

    public virtual bool CanApprove() {
        return false;
    }
}

public abstract class UnapprovedState : VacancyState {

    public UnapprovedState(vacancy) : base(vacancy) { }

    public override void Approve() {
        vacancy.State = new ApprovedState(vacancy);
    }

    public override bool CanApprove() {
        return true;
    }
}

. Это упрощает переход между состояниями, выполнение логики на основе текущего состояния или добавление новых состояний, если нам нужно:

// transition state
vacancy.State.Approve();

// conditional
model.ShowRejectButton = vacancy.State.CanReject();

Эта инкапсуляция кажется более чистой, но с учетом достаточно состояний, они тоже могут стать очень многословными. Я читал сообщение Грега Янга о неправильном использовании паттерна состояний , в котором предлагается использовать полиморфизм вместо (, поэтому я бы использовал классы ApprovedVacancy, UnapprovedVacancy и т. д.), но не вижу, как это мне поможет.

Должен ли я делегировать такие переходы между состояниями доменной службе или правильно ли я использую шаблон состояния в этой ситуации?

6
задан Dave Schweisguth 13 February 2016 в 23:14
поделиться