設計模式之狀態模式

狀態模式 State

Intro

狀態模式(State),當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。

使用場景

當一個對象的行為取決於它的狀態,並且它必須在運行時根據狀態改變它的行為時就可以考慮狀態模式。

狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把複雜的判斷邏輯簡化。

狀態模式的好處是將與特定狀態相關的行為局部化,並且將不同狀態的行為分隔開來。將特定的狀態相關的行為都放入一個對象中,由於所有與狀態相關的程式碼都存在於某個 State 中,所以通過定義新的子類可以很容易地增加新的狀態和轉換。

狀態模式通過把各種狀態轉義邏輯分布到 State 的子類之間,來減少相互之間的依賴。

Sample

class Work
{
    private WorkState _currentState;

    public Work()
    {
        _currentState = new ForenoonState();
    }

    public int Hour { get; set; }

    public bool TaskFinished { get; set; }

    public void SetState(WorkState workState)
    {
        _currentState = workState;
    }

    public void WriteProgram()
    {
        _currentState.WriteProgram(this);
    }
}


internal abstract class WorkState
{
    public abstract void WriteProgram(Work work);
}

internal class ForenoonState : WorkState
{
    public override void WriteProgram(Work work)
    {
        if (work.Hour < 12)
        {
            Console.WriteLine($"當前時間:{work.Hour}點 上午工作,精神百倍");
        }
        else
        {
            work.SetState(new NoonState());
            work.WriteProgram();
        }
    }
}

internal class NoonState : WorkState
{
    public override void WriteProgram(Work work)
    {
        if (work.Hour < 13)
        {
            Console.WriteLine($"當前時間:{work.Hour}點 餓了,午飯。犯困,午休");
        }
        else
        {
            work.SetState(new AfternoonState());
            work.WriteProgram();
        }
    }
}

internal class AfternoonState : WorkState
{
    public override void WriteProgram(Work work)
    {
        if (work.Hour < 18)
        {
            Console.WriteLine($"當前時間:{work.Hour}點 下午狀態還不錯,繼續努力");
        }
        else
        {
            work.SetState(new EveningState());
            work.WriteProgram();
        }
    }
}

internal class EveningState : WorkState
{
    public override void WriteProgram(Work work)
    {
        if (work.TaskFinished)
        {
            work.SetState(new RestState());
            work.WriteProgram();
        }
        else
        {
            if (work.Hour < 21)
            {
                Console.WriteLine($"當前時間:{work.Hour}點 還在加班啊,疲累之極");
            }
            else
            {
                work.SetState(new SleepingState());
                work.WriteProgram();
            }
        }
    }
}

internal class RestState : WorkState
{
    public override void WriteProgram(Work work)
    {
        Console.WriteLine($"當前時間:{work.Hour}點 下班回家了");
    }
}

internal class SleepingState : WorkState
{
    public override void WriteProgram(Work work)
    {
        Console.WriteLine($"當前時間:{work.Hour}點了,不行了,睡著了。");
    }
}


var emergenceWork = new Work();

emergenceWork.Hour = 9;
emergenceWork.WriteProgram();

emergenceWork.Hour = 10;
emergenceWork.WriteProgram();

emergenceWork.Hour = 12;
emergenceWork.WriteProgram();

emergenceWork.Hour = 13;
emergenceWork.WriteProgram();

emergenceWork.Hour = 14;
emergenceWork.WriteProgram();

emergenceWork.Hour = 17;
emergenceWork.WriteProgram();

emergenceWork.TaskFinished = true;//任務完成,可以提前回家了
// emergenceWork.TaskFinished = false;//任務沒完成,在公司加班吧

emergenceWork.Hour = 19;
emergenceWork.WriteProgram();

emergenceWork.Hour = 21;
emergenceWork.WriteProgram();

More

在狀態模式中,我們創建表示各種狀態的對象和一個行為隨著狀態對象改變而改變的 context 對象。

狀態模式一般用來實現狀態機,而狀態機常用在遊戲、工作流引擎等系統開發中。

有限狀態機,英文翻譯是 Finite State Machine,縮寫為 FSM,簡稱為狀態機。

狀態機有 3 個組成部分:狀態(State)、事件(Event)、動作(Action)。其中,事件也稱為轉移條件(Transition Condition)。事件觸髮狀態的轉移及動作的執行。不過,動作不是必須的,也可能只轉移狀態,不執行任何動作。

Reference