題目1:通過代碼描述每一天的不同時間段的工作效率 分析: 首先確定,工作狀態指正在工作,或者以及下班這些情況,而這些情況所受影響的因素包括:當前時間以及任務是否已經完成。所以在Work中需要兩個屬性:hour和finish。然後根據這兩個屬性直接判斷當前的工作狀態即可。 實現: 1 class Pr ...
題目1:通過代碼描述每一天的不同時間段的工作效率
分析:
首先確定,工作狀態指正在工作,或者以及下班這些情況,而這些情況所受影響的因素包括:當前時間以及任務是否已經完成。所以在Work中需要兩個屬性:hour和finish。然後根據這兩個屬性直接判斷當前的工作狀態即可。
實現:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //緊急項目 6 Work emergencyProject = new Work(); 7 emergencyProject.Hour = 9; 8 emergencyProject.WriteProgram(); 9 emergencyProject.Hour = 10; 10 emergencyProject.WriteProgram(); 11 emergencyProject.Hour = 12; 12 emergencyProject.WriteProgram(); 13 emergencyProject.Hour = 13; 14 emergencyProject.WriteProgram(); 15 emergencyProject.Hour = 14; 16 emergencyProject.WriteProgram(); 17 emergencyProject.Hour = 17; 18 emergencyProject.Finish = false; 19 emergencyProject.WriteProgram(); 20 emergencyProject.Hour = 19; 21 emergencyProject.WriteProgram(); 22 emergencyProject.Hour = 22; 23 emergencyProject.WriteProgram(); 24 25 Console.Read(); 26 } 27 public class Work 28 { 29 private int hour; 30 private bool finish = false; 31 32 public int Hour 33 { 34 get { return hour; } 35 set { hour = value; } 36 } 37 public bool Finish 38 { 39 get { return finish; } 40 set { finish = value; } 41 } 42 /// <summary> 43 /// 根據時間來判斷當前的工作狀態如何 44 /// 45 /// 方法過長 46 /// </summary> 47 public void WriteProgram() 48 { 49 if (hour < 12) 50 { 51 Console.WriteLine("當前時間:{0}點 上午工作,精神百倍", hour); 52 } 53 else if (hour < 13) 54 { 55 Console.WriteLine("當前時間:{0}點 餓了,午飯;犯困,午休", hour); 56 } 57 else if (hour < 17) 58 { 59 Console.WriteLine("當前時間:{0}點 下午狀態還不錯,繼續努力", hour); 60 } 61 else 62 { 63 if (finish) 64 { 65 Console.WriteLine("當前時間:{0}點 下班回家了", hour); 66 } 67 else 68 { 69 if (hour < 21) 70 { 71 Console.WriteLine("當前時間:{0}點 加班哦,疲憊至極", hour); 72 } 73 else 74 { 75 Console.WriteLine("當前時間:{0}點 不行了,睡著了。", hour); 76 } 77 } 78 } 79 } 80 } 81 }View Code
題目2:從1中可以很明顯的看出WriteProgram()函數幾乎承載了所有的判斷處理,且函數函數過長,所以在Work類中違背了“單一職責原則"。
分析:
面向對象設計就是希望做到代碼的責任分解,在這個情況中,我們將所有的判斷全部添加在了WriteProgram()一個函數中,不僅是函數冗長,如果我臨時添加新的情況,可能對原來判斷有出入的時間也會造成很多麻煩,對於將來的修改百害而無一利。
所以我們需要根據情況來分解函數和類。
本題目中,我們需要獲得當前的工作狀態,而這個的直接影響因素包括時間Hour和是否已經完成任務TaskFinished。
所以我們根據當前的時間可以很明顯的分為不同時間段,也就是WriteProgram()的if,else都可以自己單獨擁有一個類,他們都繼承於同一個抽象類State即可。
然後我們初始化直接進入ForenoonState類,畢竟每天早上的時間不會變,如果當前時間不再是早上,那麼我們就需要進入下一個時間段進行判斷,所以在ForenoonState類中我們需要加入判斷,如果當前時間滿足早上的時間段,顯示工作狀態,如果當前時間不再是早上的時間段,那麼我們進入下一個時間段,以此類推,找到我們當前時間段的工作狀態。
實現:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //緊急項目 6 Work emergencyProject = new Work(); 7 emergencyProject.Hour = 9; 8 emergencyProject.WriteProgram(); 9 emergencyProject.Hour = 10; 10 emergencyProject.WriteProgram(); 11 emergencyProject.Hour = 12; 12 emergencyProject.WriteProgram(); 13 emergencyProject.Hour = 13; 14 emergencyProject.WriteProgram(); 15 emergencyProject.Hour = 14; 16 emergencyProject.WriteProgram(); 17 emergencyProject.Hour = 17; 18 emergencyProject.TaskFinished = false; 19 emergencyProject.WriteProgram(); 20 emergencyProject.Hour = 19; 21 emergencyProject.WriteProgram(); 22 emergencyProject.Hour = 22; 23 emergencyProject.WriteProgram(); 24 25 Console.Read(); 26 } 27 public class Work 28 { 29 private int hour; 30 private bool finish = false; 31 private State current; 32 //初始化進入的時候是上午工作狀態 33 public Work() 34 { 35 current = new ForenoonState(); 36 } 37 public int Hour 38 { 39 get { return hour; } 40 set { hour = value; } 41 } 42 public bool TaskFinished 43 { 44 get { return finish; } 45 set { finish = value; } 46 } 47 48 public void SetState(State s) 49 { 50 current = s; 51 } 52 public void WriteProgram() 53 { 54 current.WriteProgram(this); 55 } 56 } 57 /// <summary> 58 /// 抽象狀態 59 /// </summary> 60 public abstract class State 61 { 62 public abstract void WriteProgram(Work w); 63 } 64 /// <summary> 65 /// 上午工作狀態 66 /// 67 /// 邏輯是:根據時間推移,上午工作後,移至中午午飯時間 68 /// </summary> 69 public class ForenoonState : State 70 { 71 public override void WriteProgram(Work w) 72 { 73 if (w.Hour < 12) 74 { 75 Console.WriteLine("當前時間:{0} 上午工作,精神百倍", w.Hour); 76 } 77 else 78 { 79 w.SetState(new NoonState()); 80 w.WriteProgram(); 81 } 82 } 83 } 84 /// <summary> 85 /// 中午工作狀態 86 /// 87 /// 邏輯是:根據時間推移,午休時間後,移至下午工作時間 88 /// </summary> 89 public class NoonState : State 90 { 91 public override void WriteProgram(Work w) 92 { 93 if (w.Hour < 13) 94 { 95 Console.WriteLine("當前時間:{0} 餓了,午飯;犯困,午休", w.Hour); 96 } 97 else 98 { 99 w.SetState(new AfternoonState()); 100 w.WriteProgram(); 101 } 102 } 103 } 104 /// <summary> 105 /// 下午工作狀態 106 /// 107 /// 邏輯是:根據時間推移,下午工作後,移至晚間工作狀態 108 /// </summary> 109 public class AfternoonState : State 110 { 111 public override void WriteProgram(Work w) 112 { 113 if (w.Hour < 17) 114 { 115 Console.WriteLine("當前時間:{0} 下午狀態還不錯,繼續努力", w.Hour); 116 } 117 else 118 { 119 w.SetState(new EveningState()); 120 w.WriteProgram(); 121 } 122 } 123 } 124 /// <summary> 125 /// 晚間工作狀態 126 /// 127 /// 邏輯是:已完成工作的可以準點下班,移至下班休息狀態 128 /// 未完成工作的繼續加班:這裡又分為未超過人體承受能力的(21小時)就繼續加班(此處已是最底層,沒有再多加其他的操作了) 129 /// 超過21小時的將移至睡眠狀態 130 /// </summary> 131 public class EveningState : State 132 { 133 public override void WriteProgram(Work w) 134 { 135 if (w.TaskFinished) 136 { 137 w.SetState(new RestState()); 138 w.WriteProgram(); 139 } 140 else 141 { 142 //最底層,不要再次調用,會無限往複的 143 if (w.Hour < 21) 144 { 145 Console.WriteLine("當前時間:{0} 加班哦,疲憊至極", w.Hour); 146 } 147 else 148 { 149 w.SetState(new SleepingState()); 150 w.WriteProgram(); 151 } 152 } 153 } 154 } 155 /// <summary> 156 /// 睡眠狀態 157 /// 158 /// 最底層,不要再次調用,會無限往複的 159 /// </summary> 160 public class SleepingState : State 161 { 162 public override void WriteProgram(Work w) 163 { 164 Console.WriteLine("當前時間:{0}點 不行了,睡著了", w.Hour); 165 } 166 } 167 /// <summary> 168 /// 下班休息狀態 169 /// 170 /// 最底層,不要再次調用,會無限往複的 171 /// </summary> 172 public class RestState : State 173 { 174 public override void WriteProgram(Work w) 175 { 176 if (w.TaskFinished) 177 { 178 Console.WriteLine("當前時間:{0}點 下班回家", w.Hour); 179 } 180 } 181 } 182 }View Code
總結:
這裡用到的就是狀態模式(State):當一個對象的內在狀態改變時,允許改變其行為,這個對象看起來像是改變了其類。
狀態模式主要解決的是當控制一個對象狀態轉換的調節表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以吧複雜的判斷邏輯簡化。
狀態模式的好處是將與特定狀態相關的行為局部化,並且將不同狀態的行為分割開來。
註:文中所有代碼及知識點均來自於《大話設計模式》,本人屬於邊學邊看邊敲代碼邊總結的階段。