C#設計模式之狀態模式

提高班14期郭倩_Ulrica發表於2018-06-03

前言

很好理解。這個名字讓人聽起來都很安靜。看看在設計模式裡,狀態模式是怎樣的吧

狀態模式

英文:State

what

當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像時改變了其類。
主要解決的是當一個物件狀態轉換的條件表示式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把複雜的判斷邏輯簡單化。
如果這個狀態很簡單,就沒必要用“狀態模式”了。

情景

夏天到了,我們總是由早晨的激情澎湃轉換成中午的睏意滿滿。這便是狀態發生了改變。若寫成程式碼,也許大家都會想到if 。。else和switch語句,但是一天狀態轉變的太多了,switch語句也會很多,這就造成了方法過長的壞味道。所以狀態模式就出來了~

好處與用處

好處:
將與特定狀態相關的行為區域性化,並且將不同狀態的行為分割開來。
就是說將特定的狀態相關的行為都放入一個物件中,由於所有與狀態相關的程式碼都存在於某個concrete state中,所以通過定義新的子類可以很容易地增加新的狀態和轉換。

目的:
消除龐大的條件分支語句,通過把各種狀態轉移邏輯分佈到state的子類之間,來減少相互間的依賴。

應用

當一個物件的行為取決於它的狀態,並且它必須在執行時刻根據狀態改變它的行為時,就可以考慮使用狀態模式。

程式碼展示

注意:
有過長分支判斷語句的工作類:×

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

                }
            }
        }
    }

調整後的work類:

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

    }

抽象狀態類:

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

客戶端程式碼:

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.WriteProgram();

            emergencyProjects.TaskFinished = false;

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

        }
    }

效果圖:

狀態模式

後記

直接跟著狀態模式敲,可能邏輯會出現錯誤,可以從小菜開始的時候就跟上他的步伐,一步一步將它改好~

相關文章