Development of state and domain templates

We often use simple enumerations to represent state on our entities. The problem arises when we introduce behavior that is largely state-dependent or where state transitions must comply with specific business rules.

Take the following example (which uses an enumeration to represent state):

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

You can see that this class will soon become quite verbose as we add methods for Reject, Finish, Delete, etc.

Instead, we can introduce a state template that allows us to encapsulate each state as an object:

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

This simplifies the transition between states, performs logic based on the current state, or adds new states if we need:

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

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

, , . Greg Young , ( ApprovedVacancy, UnapprovedVacancy .. ), , .

?

+6
1

, , .

, , . , , .

, State. . , , . (, vacancy.State.CanReject()), State (, vacancy.CanReject() - > bool CanReject() { return _state.CanReject(); }). , State.

, , State , . , State, , -, , - . , ( ), , , , , . ( ).

+5

All Articles