C#學(xué)習(xí)筆記之狀態(tài)模式詳解
本文通過例題為大家講解C#學(xué)習(xí)筆記之狀態(tài)模式,供大家參考,具體內(nèi)容如下
題目1:通過代碼描述每一天的不同時間段的工作效率
分析:
首先確定,工作狀態(tài)指正在工作,或者以及下班這些情況,而這些情況所受影響的因素包括:當(dāng)前時間以及任務(wù)是否已經(jīng)完成。所以在Work中需要兩個屬性:hour和finish。然后根據(jù)這兩個屬性直接判斷當(dāng)前的工作狀態(tài)即可。
實現(xiàn):
class Program
{
static void Main(string[] args)
{
//緊急項目
Work emergencyProject = new Work();
emergencyProject.Hour = 9;
emergencyProject.WriteProgram();
emergencyProject.Hour = 10;
emergencyProject.WriteProgram();
emergencyProject.Hour = 12;
emergencyProject.WriteProgram();
emergencyProject.Hour = 13;
emergencyProject.WriteProgram();
emergencyProject.Hour = 14;
emergencyProject.WriteProgram();
emergencyProject.Hour = 17;
emergencyProject.Finish = false;
emergencyProject.WriteProgram();
emergencyProject.Hour = 19;
emergencyProject.WriteProgram();
emergencyProject.Hour = 22;
emergencyProject.WriteProgram();
Console.Read();
}
public class Work
{
private int hour;
private bool finish = false;
public int Hour
{
get { return hour; }
set { hour = value; }
}
public bool Finish
{
get { return finish; }
set { finish = value; }
}
/// <summary>
/// 根據(jù)時間來判斷當(dāng)前的工作狀態(tài)如何
///
/// 方法過長
/// </summary>
public void WriteProgram()
{
if (hour < 12)
{
Console.WriteLine("當(dāng)前時間:{0}點 上午工作,精神百倍", hour);
}
else if (hour < 13)
{
Console.WriteLine("當(dāng)前時間:{0}點 餓了,午飯;犯困,午休", hour);
}
else if (hour < 17)
{
Console.WriteLine("當(dāng)前時間:{0}點 下午狀態(tài)還不錯,繼續(xù)努力", hour);
}
else
{
if (finish)
{
Console.WriteLine("當(dāng)前時間:{0}點 下班回家了", hour);
}
else
{
if (hour < 21)
{
Console.WriteLine("當(dāng)前時間:{0}點 加班哦,疲憊至極", hour);
}
else
{
Console.WriteLine("當(dāng)前時間:{0}點 不行了,睡著了。", hour);
}
}
}
}
}
}
題目2:從1中可以很明顯的看出WriteProgram()函數(shù)幾乎承載了所有的判斷處理,且函數(shù)函數(shù)過長,所以在Work類中違背了“單一職責(zé)原則"。
分析:
面向?qū)ο笤O(shè)計就是希望做到代碼的責(zé)任分解,在這個情況中,我們將所有的判斷全部添加在了WriteProgram()一個函數(shù)中,不僅是函數(shù)冗長,如果我臨時添加新的情況,可能對原來判斷有出入的時間也會造成很多麻煩,對于將來的修改百害而無一利。
所以我們需要根據(jù)情況來分解函數(shù)和類。
本題目中,我們需要獲得當(dāng)前的工作狀態(tài),而這個的直接影響因素包括時間Hour和是否已經(jīng)完成任務(wù)TaskFinished。
所以我們根據(jù)當(dāng)前的時間可以很明顯的分為不同時間段,也就是WriteProgram()的if,else都可以自己單獨擁有一個類,他們都繼承于同一個抽象類State即可。
然后我們初始化直接進入ForenoonState類,畢竟每天早上的時間不會變,如果當(dāng)前時間不再是早上,那么我們就需要進入下一個時間段進行判斷,所以在ForenoonState類中我們需要加入判斷,如果當(dāng)前時間滿足早上的時間段,顯示工作狀態(tài),如果當(dāng)前時間不再是早上的時間段,那么我們進入下一個時間段,以此類推,找到我們當(dāng)前時間段的工作狀態(tài)。

實現(xiàn):
class Program
{
static void Main(string[] args)
{
//緊急項目
Work emergencyProject = new Work();
emergencyProject.Hour = 9;
emergencyProject.WriteProgram();
emergencyProject.Hour = 10;
emergencyProject.WriteProgram();
emergencyProject.Hour = 12;
emergencyProject.WriteProgram();
emergencyProject.Hour = 13;
emergencyProject.WriteProgram();
emergencyProject.Hour = 14;
emergencyProject.WriteProgram();
emergencyProject.Hour = 17;
emergencyProject.TaskFinished = false;
emergencyProject.WriteProgram();
emergencyProject.Hour = 19;
emergencyProject.WriteProgram();
emergencyProject.Hour = 22;
emergencyProject.WriteProgram();
Console.Read();
}
public class Work
{
private int hour;
private bool finish = false;
private State current;
//初始化進入的時候是上午工作狀態(tài)
public Work()
{
current = new ForenoonState();
}
public int Hour
{
get { return hour; }
set { hour = value; }
}
public bool TaskFinished
{
get { return finish; }
set { finish = value; }
}
public void SetState(State s)
{
current = s;
}
public void WriteProgram()
{
current.WriteProgram(this);
}
}
/// <summary>
/// 抽象狀態(tài)
/// </summary>
public abstract class State
{
public abstract void WriteProgram(Work w);
}
/// <summary>
/// 上午工作狀態(tài)
///
/// 邏輯是:根據(jù)時間推移,上午工作后,移至中午午飯時間
/// </summary>
public class ForenoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 12)
{
Console.WriteLine("當(dāng)前時間:{0} 上午工作,精神百倍", w.Hour);
}
else
{
w.SetState(new NoonState());
w.WriteProgram();
}
}
}
/// <summary>
/// 中午工作狀態(tài)
///
/// 邏輯是:根據(jù)時間推移,午休時間后,移至下午工作時間
/// </summary>
public class NoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 13)
{
Console.WriteLine("當(dāng)前時間:{0} 餓了,午飯;犯困,午休", w.Hour);
}
else
{
w.SetState(new AfternoonState());
w.WriteProgram();
}
}
}
/// <summary>
/// 下午工作狀態(tài)
///
/// 邏輯是:根據(jù)時間推移,下午工作后,移至晚間工作狀態(tài)
/// </summary>
public class AfternoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 17)
{
Console.WriteLine("當(dāng)前時間:{0} 下午狀態(tài)還不錯,繼續(xù)努力", w.Hour);
}
else
{
w.SetState(new EveningState());
w.WriteProgram();
}
}
}
/// <summary>
/// 晚間工作狀態(tài)
///
/// 邏輯是:已完成工作的可以準(zhǔn)點下班,移至下班休息狀態(tài)
/// 未完成工作的繼續(xù)加班:這里又分為未超過人體承受能力的(21小時)就繼續(xù)加班(此處已是最底層,沒有再多加其他的操作了)
/// 超過21小時的將移至睡眠狀態(tài)
/// </summary>
public class EveningState : State
{
public override void WriteProgram(Work w)
{
if (w.TaskFinished)
{
w.SetState(new RestState());
w.WriteProgram();
}
else
{
//最底層,不要再次調(diào)用,會無限往復(fù)的
if (w.Hour < 21)
{
Console.WriteLine("當(dāng)前時間:{0} 加班哦,疲憊至極", w.Hour);
}
else
{
w.SetState(new SleepingState());
w.WriteProgram();
}
}
}
}
/// <summary>
/// 睡眠狀態(tài)
///
/// 最底層,不要再次調(diào)用,會無限往復(fù)的
/// </summary>
public class SleepingState : State
{
public override void WriteProgram(Work w)
{
Console.WriteLine("當(dāng)前時間:{0}點 不行了,睡著了", w.Hour);
}
}
/// <summary>
/// 下班休息狀態(tài)
///
/// 最底層,不要再次調(diào)用,會無限往復(fù)的
/// </summary>
public class RestState : State
{
public override void WriteProgram(Work w)
{
if (w.TaskFinished)
{
Console.WriteLine("當(dāng)前時間:{0}點 下班回家", w.Hour);
}
}
}
}
總結(jié):
這里用到的就是狀態(tài)模式(State):當(dāng)一個對象的內(nèi)在狀態(tài)改變時,允許改變其行為,這個對象看起來像是改變了其類。
狀態(tài)模式主要解決的是當(dāng)控制一個對象狀態(tài)轉(zhuǎn)換的調(diào)節(jié)表達(dá)式過于復(fù)雜時的情況。把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類當(dāng)中,可以吧復(fù)雜的判斷邏輯簡化。
狀態(tài)模式的好處是將與特定狀態(tài)相關(guān)的行為局部化,并且將不同狀態(tài)的行為分割開來。
注:文中所有代碼及知識點均來自于《大話設(shè)計模式》,本人屬于邊學(xué)邊看邊敲代碼邊總結(jié)的階段。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Winform之TextBox輸入日期格式驗證yyyy-mm-dd
Winform之TextBox輸入日期格式驗證yyyy-mm-dd的實例與正則表達(dá)式,需要的朋友可以參考一下2013-02-02
C#創(chuàng)建windows系統(tǒng)用戶的方法
這篇文章主要介紹了C#創(chuàng)建windows系統(tǒng)用戶的方法,涉及C#操作用戶名、密碼、顯示名稱、描述、是否強制修改密碼、密碼是否過期等技巧,非常具有實用價值,需要的朋友可以參考下2015-04-04
C#控制IE進程關(guān)閉和緩存清理的實現(xiàn)代碼
這篇文章主要介紹了C#控制IE進程關(guān)閉和緩存清理的實現(xiàn)代碼,需要的朋友可以參考下2014-04-04

