一个插排引发的设计思想 (三) 委托与事件
?
一個插排引發(fā)的設計思想 (一) 觀察者模式
一個插排引發(fā)的設計思想 (二) 抽象類與接口
一個插排引發(fā)的設計思想 (三) 委托與事件
...待續(xù)....
?
前兩篇文章循序漸進的介紹了觀察者模式、抽象類和接口, 并分析了抽象類和接口的不同.
結(jié)尾處有這樣的問題:
無論是抽象類還是接口, 都是將設備本身放入了插排的集合中,?那么我們是否可以將此處的參數(shù)改為設備的Input方法呢?
那么我們就用到了委托Delegate.
1 public delegate void InputDelegate(int left, int right);看到接下來的代碼, 老鳥別笑, 請允許我"循序漸進"的引導著思路重構(gòu).
我們用委托InputDelegate定義了插頭的標準. 那么原來的代碼改變一下
一. 用方法作為參數(shù)傳遞, 代替原來的整個設備
1 public delegate void InputDelegate(int left, int right); 2 public class OutPut 3 { 4 public OutPut() 5 { 6 this.EACollection = new List<InputDelegate>(); 7 } 8 private List<InputDelegate> EACollection; 9 public void powered(int left, int right) 10 { 11 foreach (var item in EACollection) 12 { 13 item(left, right); 14 } 15 } 16 public void AddInput(InputDelegate item) 17 { 18 EACollection.Add(item); 19 } 20 21 public void RemoveInput(InputDelegate item) 22 { 23 EACollection.Remove(item); 24 } 25 } 26 27 class Program 28 { 29 static void Main(string[] args) 30 { 31 OutPut op = new OutPut(); 32 op.AddInput(new TV().Input); 33 op.AddInput(new ElectricKettle().InputAAAA); 34 35 op.powered(220, 0); 36 37 Console.ReadKey(); 38 } 39 }原來的TV和ElectricKettle無需任何繼承任何抽象類和接口, 只要有和定義的Delegate一樣的方法簽名的方法即可.
甚至名字都可以不一樣, 例如ElectricKettle的input方法我隨便改了一下改成了InputAAAA依然沒問題.
1 public class ElectricKettle 2 { 3 public void InputAAAA(int left, int right) 4 { 5 Heat(); 6 } 7 8 private void Heat() 9 { 10 Console.WriteLine("I am heating"); 11 } 12 }通過上面的方法, 我們把插入插排的參數(shù)由整個設備改成了設備的插頭.?
功能是實現(xiàn)了, 但Delegate用起來沒必要那么麻煩, 我們繼續(xù)改
二. 用+=和-=來操作
我們改造一下Output類
1 public delegate void InputDelegate(int left, int right); 2 public class OutPut 3 { 4 public InputDelegate inputDelegate; 5 public void powered(int left, int right) 6 { 7 inputDelegate(left, right); 8 } 9 } 10 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 OutPut op = new OutPut(); 16 op.inputDelegate += new TV().Input; 17 op.inputDelegate += new ElectricKettle().InputAAAA; 18 19 op.powered(220, 0); 20 21 Console.ReadKey(); 22 } 23 }簡潔多了, 根據(jù)Delegate的特性, 插排集本身也被inputDelegate代替了.
在調(diào)用的時候, 我們只需將input方法 +=到該inputDelegate即可.
三. 委托和事件
上面的例子貌似已經(jīng)很好了, 但既然是插排, 也就是可能會有好多插頭來插拔, 而插頭之間互不干涉, 調(diào)用的位置可能存在于系統(tǒng)的任何位置 .
但上面的代碼讓我們想到一個問題,
我們把"集和"暴露出來了, 之前的 private List<IGBElectricalable> EACollection是私有的, 只可以通過add和 remove兩個方法操作.
現(xiàn)在我們把它public了,? 哪個搗蛋的寫了一句op.inputDelegate = null,? 把插排都弄沒了, 讓別的插頭怎么辦.
所以我們還希望像原來那樣只提供增減的方法, 不允許賦值, 這里我們就用到了事件.
1 public delegate void InputDelegate(int left, int right); 2 3 public class OutPut 4 { 5 public event InputDelegate inputEvent; 6 public void powered(int left, int right) 7 { 8 inputEvent(left, right); 9 } 10 } 11 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 OutPut op = new OutPut(); 17 18 op.inputEvent += new TV().Input; 19 op.inputEvent += new ElectricKettle().InputAAAA; 20 //op.inputEvent = null; 21 op.powered(220, 0); 22 23 Console.ReadKey(); 24 } 25 }Output中的 inputDelegate 改為了 inputEvent,?inputEvent不再允許通過=來賦值了.
main方法中注釋的一行?//op.inputEvent = null; 測試了一下 , 已經(jīng)編譯不通過了.
四. 小結(jié)
本文通過委托, 將方法作為參數(shù)注冊到了插排中.? 因為安全問題, 又將委托改為了事件.
?
總結(jié)
以上是生活随笔為你收集整理的一个插排引发的设计思想 (三) 委托与事件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Jenkins]Error:403 N
- 下一篇: pfSense如何创建和配置VLAN