《丁丁历险记系列之委托》-- 摘自http://www.cnblogs.com/xfxxx/archive/2010/04/03/1703839.html...
生活随笔
收集整理的這篇文章主要介紹了
《丁丁历险记系列之委托》-- 摘自http://www.cnblogs.com/xfxxx/archive/2010/04/03/1703839.html...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文根據《.NET委托:一個C#睡前故事》改編,我的初衷是通過一個類似于小說的模式,使用C#語言為背景,將編程的基礎知識以一種很容易理解的方式展現給初學者。
雖然我還有日常的工作要做,其中包括C#的培訓工作(本文也是我曾經用于培訓學生時一堂課的內容),但我會盡量抽時間,爭取陸續的推出該系列的其它姊妹篇。
下面的代碼使用起來非常簡單的,直接粘貼到命令行項目中的Program中即可運行,運行有兩種模式,一種是單步運行,修改?ExecuteStep(1);中的參數1-9
另一種是注釋該語句,取消注釋下面的for循環兩行,編譯運行即可。而且,給讀者的感覺看代碼就像看小說一樣有趣!
?
1 using System;2
3 ?class Market
4 {
5
6 #region 故事開始
7
8 //從前,在南方一塊奇異的土地上,有個程序員名叫丁丁,他在一家知名的軟件公司M公司負責產品的市場促銷工作。
9 //他非常勤奮,對他的老板總是百依百順,但是他的老板從不信任別人,堅決要求隨時知道丁丁的工作進度,以防止他偷懶。
10 //丁丁是個喜歡思考的人,但是由于原先沒有經驗,他只能自己摸索著一步一步的找到了完美的解決方案。
11 //下面,讓我們跟隨著丁丁的足跡,探尋他是怎樣成長和進步的。
12 ?
13 static void Main()
14 {
15 //您只需要修改下面的參數1-9,然后編譯運行即可看到不同的運行結果
16 ? ExecuteStep(1);
17 //或者使用這個循環,遍歷所有結果
18 //for (int i = 1; i < 10; i++)
19 //ExecuteStep(i);
20 ? }
21
22 static void ExecuteStep(int step)
23 {
24 switch (step)
25 {
26 case 1: ED1_通知方法(); break;
27 case 2: ED2_接口(); break;
28 case 3: ED3_委托(); break;
29 case 4: ED4_靜態監聽者(); break;
30 case 5: ED5_事件(); break;
31 case 6: ED6_收獲所有結果(); break;
32 case 7: ED7_異步通知_激發(); break;
33 case 8: ED8_異步通知_輪詢(); break;
34 case 9: ED9_異步通知_回調(); break;
35 }
36 }
37
38 #endregion
39
40 #region 通知方法
41
42 //首先丁丁考慮的是怎樣能不讓老板呆在他的辦公室里站在背后盯著他,于是就對老板做出承諾:無論何時,
43 //只要我的工作取得了一點進展我都會及時讓你知道。
44 //丁丁通過周期性地使用“帶類型的引用(typed reference)”來“回調”他的老板來實現他的承諾:
45 ?
46 #region Boss1類
47 class Boss1
48 {
49 public void WorkStarted() { /* 老板不關心。*/ }
50 public void WorkProgressing() { /* 老板不關心。*/ }
51 public int WorkCompleted()
52 {
53 Console.WriteLine("老板評價:仍需努力!給 1 分");
54 return 1; //總分為10
55 ? }
56 }
57 #endregion
58
59 #region Worker1類
60 class Worker1
61 {
62 Boss1 _boss;
63 public void Advise(Boss1 boss)
64 {
65 _boss = boss;
66 }
67
68 public void DoWork()
69 {
70 Console.WriteLine("丁丁:工作開始");
71 if (_boss != null)
72 _boss.WorkStarted();
73
74 Console.WriteLine("丁丁:工作進行中");
75 if (_boss != null)
76 _boss.WorkProgressing();
77
78 Console.WriteLine("丁丁:工作完成!自我打分: 3 分");
79 if (_boss != null)
80 {
81 int grade = _boss.WorkCompleted();
82 Console.WriteLine("丁丁的工作得分=" + grade);
83 }
84 }
85 }
86 #endregion
87
88 private static void ED1_通知方法()
89 {
90 Console.WriteLine("ED1_通知方法---------------------------------------");
91 Worker1 dingding = new Worker1();
92 Boss1 boss = new Boss1();
93 dingding.Advise(boss);
94 dingding.DoWork();
95 Console.WriteLine("公司消息:產品促銷工作順利結束!");
96 Console.ReadLine();
97 }
98
99 #endregion
100
101 #region 接口
102
103 //現在,丁丁成了一個特殊的人,他不但能容忍吝嗇的老板,而且和他周圍的市場中的客戶也有了密切的聯系,
104 //以至于他認為市場中所有客戶對他的工作進度也感興趣。不幸的是,他必須也給市場添加一個特殊的回調函數Advise
105 //來實現同時向他老板和市場報告工作進度。丁丁想要把潛在的通知的列表和這些通知的實現方法分離開來,
106 //于是他決定把方法分離為一個接口:IWorkerEvents
107 ?
108 #region IWorkerEvents接口
109 public interface IWorkerEvents
110 {
111 void WorkStarted();
112 void WorkProgressing();
113 int WorkCompleted();
114 }
115 #endregion
116
117 #region Boss2類
118 class Boss2 : IWorkerEvents
119 {
120 public void WorkStarted() { /* 老板不關心。*/ }
121 public void WorkProgressing() { /* 老板不關心。*/ }
122 public int WorkCompleted()
123 {
124 Console.WriteLine("老板評價:還可以!給 4 分");
125 return 4;
126 }
127 }
128 #endregion
129
130 #region Worker2類
131 class Worker2
132 {
133 public void Advise(IWorkerEvents events)
134 {
135 _events = events;
136 }
137
138 public void DoWork()
139 {
140 Console.WriteLine("丁丁:工作開始");
141 if (_events != null)
142 _events.WorkStarted();
143 Console.WriteLine("丁丁:工作進行中");
144 if (_events != null)
145 _events.WorkProgressing();
146 Console.WriteLine("丁丁:工作完成!自我打分: 4 分");
147 if (_events != null)
148 {
149 int grade = _events.WorkCompleted();
150 Console.WriteLine("丁丁的工作得分=" + grade);
151 }
152 }
153 private IWorkerEvents _events;
154 }
155 #endregion
156
157 private static void ED2_接口()
158 {
159 Console.WriteLine("ED2_接口---------------------------------------");
160 Worker2 dingding = new Worker2();
161 Boss2 boss = new Boss2();
162 dingding.Advise(boss);
163 dingding.DoWork();
164 Console.WriteLine("公司消息:產品促銷工作順利結束!");
165 Console.ReadLine();
166 }
167
168 #endregion
169
170 #region 委托
171
172 //不幸的是,這沒有解決問題。每當丁丁忙于通過接口的實現和老板交流時,就沒有機會及時通知市場了。
173 //至少他不能忽略身在遠方的老板的引用,以此來讓市場中的其他實現了IWorkerEvents的客戶得到他的工作報告。
174 //他的老板還是抱怨得很厲害。“丁丁!”他老板吼道,“你為什么在工作一開始和工作進行中都來煩我?!
175 //我不關心這些事件。你不但強迫我實現了這些方法,而且還在浪費我寶貴的工作時間來處理你的事件,
176 //特別是當我外出的時候更是如此!你能不能不再來煩我?”
177 //于是,丁丁意識到接口雖然在很多情況都很有用,但是當用作事件時,“效果”不夠好。
178 //他希望能夠僅在別人想要時才通知他們,于是他決定把接口的方法分離為單獨的委托,
179 //每個委托都像一個小的接口方法:
180
181 #region 委托類型的定義
182 public delegate void WorkStarted();
183 public delegate void WorkProgressing();
184 public delegate int WorkCompleted();
185 #endregion
186
187 #region Boss3類
188 class Boss3
189 {
190 public int WorkCompleted()
191 {
192 Console.WriteLine("老板評價:很好!給 7 分");
193 return 7;
194 }
195 }
196 #endregion
197
198 #region Worker3類
199 class Worker3
200 {
201 public WorkStarted started;
202 public WorkProgressing progressing;
203 public WorkCompleted completed;
204
205 public void DoWork()
206 {
207 Console.WriteLine("丁丁:工作開始");
208 if (started != null)
209 started();
210 Console.WriteLine("丁丁:工作進行中");
211 if (progressing != null)
212 progressing();
213 Console.WriteLine("丁丁:工作完成!自我打分: 5 分");
214 if (completed != null)
215 {
216 int grade = completed();
217 Console.WriteLine("丁丁的工作得分=" + grade);
218 }
219 }
220 }
221 #endregion
222
223 private static void ED3_委托()
224 {
225 Console.WriteLine("ED3_委托---------------------------------------");
226 Worker3 dingding = new Worker3();
227 Boss3 boss = new Boss3();
228 dingding.completed = new WorkCompleted(boss.WorkCompleted);
229 dingding.DoWork();
230 Console.WriteLine("公司消息:產品促銷工作順利結束!");
231 Console.ReadLine();
232 }
233
234 #endregion
235
236 #region 靜態監聽者
237
238 //這樣,丁丁不會再拿他老板不想要的事件來煩他老板了,但是他還沒有把市場放到他的監聽者列表中。
239 //因為市場是個包涵一切的實體,看來不適合使用實例方法的委托(想像一下,實例化一個市場中的所有客戶要花費多少資源!)
240 //于是丁丁就需要能夠對靜態委托進行掛鉤,委托對這一點支持得很好
241
242 static void WorkerStartedWork1()
243 {
244 Console.WriteLine("市場知道M公司已經開始產品促銷了!");
245 }
246
247 static int WorkerCompletedWork1()
248 {
249 Console.WriteLine("市場很滿意M公司的產品促銷活動!給 5 分");
250 return 5;
251 }
252
253 private static void ED4_靜態監聽者()
254 {
255 Console.WriteLine("ED4_靜態監聽者---------------------------------------");
256 Worker3 dingding = new Worker3();
257 Boss3 boss = new Boss3();
258 dingding.completed += new WorkCompleted(boss.WorkCompleted);
259 dingding.started += new WorkStarted(Market.WorkerStartedWork1);
260 dingding.completed += new WorkCompleted(Market.WorkerCompletedWork1);
261 dingding.DoWork();
262 Console.WriteLine("公司消息:產品促銷工作順利結束!");
263 Console.ReadLine();
264 }
265
266 #endregion
267
268 #region 事件
269
270 //不幸的是,市場太繁忙了,也不習慣時刻關注它里面的個體,它可以用自己的委托替換了丁丁老板的委托。
271 //這是把丁丁的Worker類的的委托字段做成public的一個無意識的副作用。
272 //同樣,如果丁丁的老板不耐煩了,也可以決定自己來激發丁丁的委托(真是一個粗魯的老板):
273 //丁丁的老板可以使用下面的方法來親手強制其完成工作
274 //if(dingding.completed != null) dingding.completed();
275
276 //丁丁不想讓這些事發生,他意識到需要給每個委托提供“注冊”和“反注冊”的功能,
277 //這樣監聽者就可以自己添加和移除委托,但同時又不能清空整個列表也不能隨意激發丁丁的事件了。
278 //丁丁并沒有來自己實現這些功能,相反,他使用了event關鍵字讓C#編譯器為他構建這些方法:
279
280 //丁丁知道event關鍵字在委托的外邊包裝了一個Property,僅讓客戶通過+=和-=操作符來添加和移除,
281 //強迫他的老板和市場正確地使用事件。
282
283 #region Worker4類
284 class Worker4
285 {
286 public event WorkStarted started;
287 public event WorkProgressing progressing;
288 public event WorkCompleted completed;
289
290 public void DoWork()
291 {
292 Console.WriteLine("丁丁:工作開始");
293 if (started != null) started();
294 Console.WriteLine("丁丁:工作進行中");
295 if (progressing != null) progressing();
296 Console.WriteLine("丁丁:工作完成!自我打分: 6 分");
297 if (completed != null)
298 {
299 int grade = completed();
300 Console.WriteLine("丁丁的工作得分=" + grade);
301 }
302 }
303 }
304 #endregion
305
306 private static void ED5_事件()
307 {
308 Console.WriteLine("ED5_事件---------------------------------------");
309 Worker4 dingding = new Worker4();
310 Boss3 boss = new Boss3();
311 dingding.completed += new WorkCompleted(boss.WorkCompleted);
312 dingding.started += new WorkStarted(Market.WorkerStartedWork1);
313 dingding.completed += new WorkCompleted(Market.WorkerCompletedWork1);
314 dingding.DoWork();
315 Console.WriteLine("公司消息:產品促銷工作順利結束!");
316 Console.ReadLine();
317 }
318
319 #endregion
320
321 #region "收獲"所有結果
322
323 //到這時,丁丁終于可以送一口氣了,他成功地滿足了所有監聽者的需求,同時避免了與特定實現的緊耦合。
324 //但是他注意到他的老板和市場都為它的工作打了分,但是他僅僅接收了一個分數。
325 //面對多個監聽者,他想要"收獲"所有的結果,于是他深入到代理里面,輪詢監聽者列表,手工一個個調用:
326
327 #region Worker5類
328 class Worker5
329 {
330 public event WorkStarted started;
331 public event WorkProgressing progressing;
332 public event WorkCompleted completed;
333
334 public void DoWork()
335 {
336 Console.WriteLine("丁丁:工作開始");
337 if (started != null) started();
338 Console.WriteLine("丁丁:工作進行中");
339 if (progressing != null) progressing();
340 Console.WriteLine("丁丁:工作完成!自我打分: 7 分");
341 if (completed != null)
342 {
343 //遍歷代理中的所有委托對象,依次獲取結果
344 foreach (WorkCompleted wc in completed.GetInvocationList())
345 {
346 int grade = wc();
347 Console.WriteLine("丁丁的工作得分=" + grade);
348 }
349 }
350 }
351 }
352 #endregion
353
354 private static void ED6_收獲所有結果()
355 {
356 Console.WriteLine("ED6_收獲所有結果---------------------------------------");
357 Worker5 dingding = new Worker5();
358 Boss3 boss = new Boss3();
359 dingding.completed += new WorkCompleted(boss.WorkCompleted);
360 dingding.started += new WorkStarted(Market.WorkerStartedWork1);
361 dingding.completed += new WorkCompleted(Market.WorkerCompletedWork1);
362 dingding.DoWork();
363 Console.WriteLine("公司消息:產品促銷工作順利結束!");
364 Console.ReadLine();
365 }
366
367 #endregion
368
369 #region 異步通知:激發
370
371 //同時,他的老板和市場還要忙于處理其他事情,也就是說他們給丁丁打分所花費的事件變得非常長:
372 //很不幸,丁丁每次通知一個監聽者后必須等待它給自己打分,現在這些通知花費了他太多的工作時間。
373 //于是他決定忘掉分數,僅僅異步激發事件:
374
375 #region Boss4類
376 class Boss4
377 {
378 public int WorkCompleted()
379 {
380 System.Threading.Thread.Sleep(3000);
381 Console.WriteLine("老板評價:非常好!給 10 分");
382 return 10;
383 }
384 }
385 #endregion
386
387 #region Worker6類
388 class Worker6
389 {
390 public event WorkStarted started;
391 public event WorkProgressing progressing;
392 public event WorkCompleted completed;
393
394 public void DoWork()
395 {
396 Console.WriteLine("丁丁:工作開始");
397 if (started != null) started();
398 Console.WriteLine("丁丁:工作進行中");
399 if (progressing != null) progressing();
400 Console.WriteLine("丁丁:工作完成!自我打分: 8 分");
401 if (completed != null)
402 {
403 foreach (WorkCompleted wc in completed.GetInvocationList())
404 {
405 wc.BeginInvoke(null, null);
406 }
407 }
408 }
409 }
410 #endregion
411
412 static void WorkerStartedWork2()
413 {
414 Console.WriteLine("市場知道M公司已經開始產品促銷了!");
415 }
416
417 static int WorkerCompletedWork2()
418 {
419 //暫停進程一段時間以模擬繁忙程度
420 System.Threading.Thread.Sleep(4000);
421 Console.WriteLine("市場很滿意M公司的產品促銷活動!給 10 分");
422 return 10;
423 }
424
425 private static void ED7_異步通知_激發()
426 {
427 Console.WriteLine("ED7_異步通知_激發---------------------------------------");
428 Worker6 dingding = new Worker6();
429 Boss4 boss = new Boss4();
430 dingding.completed += new WorkCompleted(boss.WorkCompleted);
431 dingding.started += new WorkStarted(Market.WorkerStartedWork2);
432 dingding.completed += new WorkCompleted(Market.WorkerCompletedWork2);
433 dingding.DoWork();
434 Console.WriteLine("公司消息:產品促銷工作順利結束!");
435 Console.ReadLine();
436 }
437
438 #endregion
439
440 #region 異步通知:輪詢
441
442 //這使得丁丁可以通知他的監聽者,然后立即返回工作,讓進程的線程池來調用這些代理。隨著時間的過去,
443 //丁丁發現他丟失了他工作的反饋,他知道聽取別人的贊揚和努力工作一樣重要,于是他不但異步激發事件,
444 //還要周期性地輪詢,取得可用的分數。
445
446 #region Worker7類
447 class Worker7
448 {
449 public event WorkStarted started;
450 public event WorkProgressing progressing;
451 public event WorkCompleted completed;
452
453 public void DoWork()
454 {
455 Console.WriteLine("丁丁:工作開始");
456 if (started != null) started();
457 Console.WriteLine("丁丁:工作進行中");
458 if (progressing != null) progressing();
459 Console.WriteLine("丁丁:工作完成!自我打分: 9 分");
460 if (completed != null)
461 {
462 foreach (WorkCompleted wc in completed.GetInvocationList())
463 {
464 IAsyncResult res = wc.BeginInvoke(null, null);
465 while (!res.IsCompleted)
466 System.Threading.Thread.Sleep(1);
467 int grade = wc.EndInvoke(res);
468 Console.WriteLine("丁丁的工作得分=" + grade);
469 }
470 }
471 }
472 }
473 #endregion
474
475 private static void ED8_異步通知_輪詢()
476 {
477 Console.WriteLine("ED8_異步通知_輪詢---------------------------------------");
478 Worker7 dingding = new Worker7();
479 Boss4 boss = new Boss4();
480 dingding.completed += new WorkCompleted(boss.WorkCompleted);
481 dingding.started += new WorkStarted(Market.WorkerStartedWork2);
482 dingding.completed += new WorkCompleted(Market.WorkerCompletedWork2);
483 dingding.DoWork();
484 Console.WriteLine("公司消息:產品促銷工作順利結束!");
485 Console.ReadLine();
486 }
487
488 #endregion
489
490 #region 異步通知:回調
491
492 //不幸地,丁丁有回到了一開始就想避免的情況中來,比如,老板站在背后盯著他工作。
493 //于是,他決定使用自己的委托回調函數作為他調用的異步委托完成的通知,讓他自己立即回到工作,
494 //但是仍可以在別人給他的工作打分后得到通知:
495
496 #region Worker8類
497 class Worker8
498 {
499 public event WorkStarted started;
500 public event WorkProgressing progressing;
501 public event WorkCompleted completed;
502
503 public void DoWork()
504 {
505 Console.WriteLine("丁丁:工作開始");
506 if (started != null) started();
507 Console.WriteLine("丁丁:工作進行中");
508 if (progressing != null) progressing();
509 Console.WriteLine("丁丁:工作完成!自我打分: 10 分");
510 if (completed != null)
511 {
512 foreach (WorkCompleted wc in completed.GetInvocationList())
513 {
514 wc.BeginInvoke(new AsyncCallback(WorkGraded), wc);
515 }
516 }
517 }
518
519 private void WorkGraded(IAsyncResult res)
520 {
521 WorkCompleted wc = (WorkCompleted)res.AsyncState;
522 int grade = wc.EndInvoke(res);
523 Console.WriteLine("丁丁的工作得分=" + grade);
524 }
525 }
526 #endregion
527
528 private static void ED9_異步通知_回調()
529 {
530 Console.WriteLine("ED9_異步通知_回調---------------------------------------");
531 Worker8 dingding = new Worker8();
532 Boss4 boss = new Boss4();
533 dingding.completed += new WorkCompleted(boss.WorkCompleted);
534 dingding.started += new WorkStarted(Market.WorkerStartedWork2);
535 dingding.completed += new WorkCompleted(Market.WorkerCompletedWork2);
536 dingding.DoWork();
537 Console.WriteLine("公司消息:產品促銷工作順利結束!");
538 Console.ReadLine();
539 }
540
541 #endregion
542
543 #region 尾聲
544
545 //整個軟件市場的繁榮
546 //丁丁、他的老板和市場最終都滿足了。丁丁的老板和市場可以收到他們感興趣的事件通知,
547 //減少了實現的負擔和非必需的往返“差旅費”。丁丁可以通知他們,而不管他們要花多長時間來從目的方法中返回,
548 //同時又可以異步地得到他的結果。丁丁知道,這并不簡單,因為當他異步激發事件時,
549 //方法要在另外一個線程中執行,丁丁的目的方法完成的通知也是一樣的道理。
550 //于是丁丁便開始著手研究線程了……<本章完>
551
552 #endregion
553
554 }
?
轉載于:https://www.cnblogs.com/liming1019/archive/2010/07/26/1785636.html
總結
以上是生活随笔為你收集整理的《丁丁历险记系列之委托》-- 摘自http://www.cnblogs.com/xfxxx/archive/2010/04/03/1703839.html...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网的三大巨头 百度 阿里巴巴 腾讯(
- 下一篇: 中国智慧停车行业未来前景展望及项目运营规