狀態模式

1. 工做狀態-函數版

A: 還在面向過程。
A: 這是起碼的面向對象思惟,至少應該有個工做類,你的寫程序方法是類方法,而鐘點,任務完成其實就是類的什麼?
B: 對外屬性?ide

2. 工做狀態-分類版

class Program
{
    static void Main(string[] args)
    {
        //緊急項目
        Work emergencyProjects = new Work();
        emergencyProjects.Hour = 9;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 10;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 12;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 13;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 14;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 17;

        //emergencyProjects.WorkFinished = true;
        emergencyProjects.TaskFinished = false;

        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 19;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 22;
        emergencyProjects.WriteProgram();

        Console.Read();
    }
}

//工做
public class Work
{
    //鐘點
    private int hour;
    public int Hour
    {
        get { return hour; }
        set { hour = value; }
    }

    //任務完成
    private bool finish = false;
    public bool TaskFinished
    {
        get { return finish; }
        set { finish = value; }
    }


    public void WriteProgram()
    {
        if (hour < 12)
        {
            Console.WriteLine("當前時間:{0}點 上午工做,精神百倍", hour);
        }
        else if (hour < 13)
        {
            Console.WriteLine("當前時間:{0}點 餓了,午餐;犯困,午休。", hour);
        }
        else if (hour < 17)
        {
            Console.WriteLine("當前時間:{0}點 下午狀態還不錯,繼續努力", hour);
        }
        else
        {
            if (finish)
            {
                Console.WriteLine("當前時間:{0}點 下班回家了", hour);
            }
            else
            {
                if (hour < 21)
                {
                    Console.WriteLine("當前時間:{0}點 加班哦,疲累之極", hour);
                }
                else
                {
                    Console.WriteLine("當前時間:{0}點 不行了,睡着了。", hour);
                }
            }
        }
    }
}

3. 方法過程是壞味道

B: 面向對象設計其實就是但願作到代碼的職責分解。這個類違背了'單一職責原則'。
A: 這裏有太多的判斷,使得任何需求的改動或增長,都須要去更改這個方法。可是真正改動的地方只涉及17點到22點的狀態,可是目前的代碼倒是對整個方法作改動,維護出錯的風險很大。
B: 違背了開放-封閉原則。
A: 把這些分支想辦法變成一個又一個的類,增長時不會影響其餘類。而後狀態的變化在各自的類中完成。函數

4. 狀態模式

當一個對象的內部狀態改變時容許改變其行爲,這個對象看起來像是改變了其類。

A: 狀態模式主要解決的是當控制一個對象狀態轉化的條件表達式過於複雜時的狀況。把狀態的判斷邏輯轉移到表示不一樣狀態的一系列類單中,能夠把複雜的判斷邏輯簡化。若是判斷很簡單,固然不必這樣作。
圖1this

class Program
{
    static void Main(string[] args)
    {
        Context c = new Context(new ConcreteStateA());

        c.Request();
        c.Request();
        c.Request();
        c.Request();

        Console.Read();
    }
}

class Context
{
    private State state;

    public Context(State state)
    {
        this.state = state;
    }

    public State State
    {
        get
        {
            return state;
        }
        set
        {
            state = value;
            Console.WriteLine("當前狀態:" + state.GetType().Name);
        }
    }

    public void Request()
    {
        state.Handle(this);
    }
}

abstract class State
{
    public abstract void Handle(Context context);
}

class ConcreteStateA : State
{
    public override void Handle(Context context)
    {
        context.State = new ConcreteStateB();
    }
}

class ConcreteStateB : State
{
    public override void Handle(Context context)
    {
        context.State = new ConcreteStateA();
    }
}

5. 狀態模式的好處與用處

A: 將特定狀態相關的行爲局部化,而且將不一樣狀態的行爲分割開來。
B: 是否是將特定的狀態相關的行爲都放入一個對象中,因爲全部與狀態相關的代碼都存在於某個ConcreteState中,全部經過定義新的子類能夠很容易地增長新的狀態和轉換。
A: 目的是爲了消除龐大的條件分支,大的分支判斷會使得它們難以修改和擴展。狀態模式經過把各類狀態轉移邏輯分佈到State的子類之間,來減小相互間的依賴。
A: 當一個對象的行爲取決以它的狀態,而且它必須在運行時刻根據狀態改變它的行爲時,就能夠考慮使用狀態模式了。多個狀態,且狀態的變化都是依靠大量的分支判斷語句來實現,此時應該考慮將每一種業務狀態定義爲一個State的子類。這樣這些對象就能夠不依賴其餘對象而獨立變化。某一天客戶須要更改需求,增長或減小業務狀態或改變狀態流程,對你來講都不是困難的事。spa

6. 工做狀態-狀態模式版

圖1

class Program
{
    static void Main(string[] args)
    {
        //緊急項目
        Work emergencyProjects = new Work();
        emergencyProjects.Hour = 9;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 10;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 12;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 13;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 14;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 17;

        //emergencyProjects.WorkFinished = true;
        emergencyProjects.TaskFinished = false;

        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 19;
        emergencyProjects.WriteProgram();
        emergencyProjects.Hour = 22;
        emergencyProjects.WriteProgram();


        Console.Read();
    }
}


//抽象狀態
public abstract class State
{
    public abstract void WriteProgram(Work w);
}

//上午工做狀態
public class ForenoonState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.Hour < 12)
        {
            Console.WriteLine("當前時間:{0}點 上午工做,精神百倍", w.Hour);
        }
        else
        {
            w.SetState(new NoonState());
            w.WriteProgram();
        }
    }
}

//中午工做狀態
public class NoonState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.Hour < 13)
        {
            Console.WriteLine("當前時間:{0}點 餓了,午餐;犯困,午休。", w.Hour);
        }
        else
        {
            w.SetState(new AfternoonState());
            w.WriteProgram();
        }
    }
}

//下午工做狀態
public class AfternoonState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.Hour < 17)
        {
            Console.WriteLine("當前時間:{0}點 下午狀態還不錯,繼續努力", w.Hour);
        }
        else
        {
            w.SetState(new EveningState());
            w.WriteProgram();
        }
    }
}

//晚間工做狀態
public class EveningState : State
{
    public override void WriteProgram(Work w)
    {
        if (w.TaskFinished)
        {
            w.SetState(new RestState());
            w.WriteProgram();
        }
        else
        {
            if (w.Hour < 21)
            {
                Console.WriteLine("當前時間:{0}點 加班哦,疲累之極", w.Hour);
            }
            else
            {
                w.SetState(new SleepingState());
                w.WriteProgram();
            }
        }
    }
}

//睡眠狀態
public class SleepingState : State
{
    public override void WriteProgram(Work w)
    {
        Console.WriteLine("當前時間:{0}點 不行了,睡着了。", w.Hour);
    }
}

//下班休息狀態
public class RestState : State
{
    public override void WriteProgram(Work w)
    {
        Console.WriteLine("當前時間:{0}點 下班回家了", w.Hour);
    }
}

//工做
public class Work
{
    private State current;
    public Work()
    {
        current = new ForenoonState();
    }

    private double hour;
    public double Hour
    {
        get { return hour; }
        set { hour = value; }
    }

    private bool finish = false;
    public bool TaskFinished
    {
        get { return finish; }
        set { finish = value; }
    }


    public void SetState(State s)
    {
        current = s;
    }

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

B: 增長個強制下班狀態,並改動一下傍晚工做狀態類的判斷就可了。而這是不影響其餘狀態的代碼的。設計

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息