详解事件和委托
委托
委托實(shí)質(zhì)上是一個(gè)類,是對方法/函數(shù)的封裝,是一種引用方法的類型,可以當(dāng)作給方法的特定特征指定一個(gè)名稱。委托內(nèi)部有三個(gè)重要成員:目標(biāo),方法,前一個(gè)委托。一旦為委托分配了方法,委托將與該方法具有完全相同的行為。委托對象使用關(guān)鍵字delegate來聲明。
普通代碼里這樣調(diào)用方法:
aBird.Fly();封裝到委托里,aBird 就是目標(biāo),Fly 就是方法。委托可以組成鏈,“前一個(gè)委托”用于支持這種鏈?zhǔn)浇Y(jié)構(gòu)。
MethodInvoker mi = new MethodInvoker(aBird.Fly); mi();這段和上面的 aBird.Fly 是一個(gè)效果,但不是直接調(diào)用。可以將 mi 傳遞到其他地方,再進(jìn)行調(diào)用。委托在方法和調(diào)用方之間建立了間接性。 事件是基于委托的通信機(jī)制。如果一個(gè)對象的狀態(tài)改變了,我們可能希望將這種改變通知給外界。
從實(shí)現(xiàn)角度看,“通知”其實(shí)就是調(diào)用接收方的方法。困境在于,我們不知道誰對這些改變有興趣,有多少人對這些改變有興趣,所以,我們無法直接調(diào)用方法。
.net中有兩個(gè)辦法解決這個(gè)問題,接口和委托。
這兩個(gè)的含義都是“約定”,目的則是“分離”,換句話說,就是:商量好了,分頭行動(dòng)。接口是對類成員的約定,委托是對參數(shù)和返回值的約定。對于簡單的通知,接口有些麻煩,委托更好一些,所以,我們將一個(gè)委托加到類中,讓它保存應(yīng)該調(diào)用的方法。但光禿禿的一個(gè)字段有點(diǎn)難看,好像沒穿衣服一樣。為了讓代碼更好看,.net 引入了事件的概念。
事件
而事件則是委托的一種特殊形式,在發(fā)生其他類或?qū)ο箨P(guān)注的事情時(shí),類或?qū)ο罂赏ㄟ^事件通知它們(事件對象來處理這個(gè)通知過程)。
事件本質(zhì)上是一個(gè)方法,事件提供 add, remove,將方法掛到這個(gè)委托中,或從此委托中移除。像這樣:
//訂閱事件 button1.Click += new EventHandler(button1_Click); //退閱事件 button1.Click -= new EventHandler(button1_Click);如果A訂閱了B的事件,那么它們之間的引用關(guān)系是這樣:B引用委托,委托引用A。
這就是說,在退閱事件之前,A不會(huì)被當(dāng)作垃圾回收,因?yàn)锽包含對它的引用。
因此,委托和事件的區(qū)別是:委托與類,結(jié)構(gòu),接口,枚舉是一類,而事件屬類成員,和屬性,方法,字段是一類。
綜合實(shí)例應(yīng)用
Class Cat{private String name;public Cat(String name){this.name = name;}//聲明一個(gè)名為CatShoutEventHandler的委托public delegate void CatShoutEventHandler();//聲明事件CatShout,它的事件類型是委托CatShoutEventHandlerpublic event CatShoutEventHandler CatShout CatShout;public void shout(){System.out.println("I am cat " + name + ".");//當(dāng)執(zhí)行Shout()方法時(shí),如果CatShout中有對象登記事件,則執(zhí)行CatShoutif(CatShout != null){CatShout();}}}該類中的CatShout()是無參數(shù)無返回值的方法,因?yàn)槭录﨏atShout的類型是委托CatShoutEventHandler,而CatShoutEventHandler就是無參數(shù)、無返回值的。
Class Mouse{private String name;public Mouse(String name){this.name = name;}public void run(){System.out.println("Cat is comming ," + name + " run!");}} //測試方法 public static void main(String[] args){Cat cat = new Cat("Tom");Mouse JerryMouse = new Mouse("Jerry");Mouse JackMouse = new Mouse("Jack");//將Mouse的run()方法通過實(shí)例化委托Cat.CatShoutEventHandler登記到Cat事件CatShout當(dāng)中cat.CatShout += new CatShoutEventHandler(JerryMouse.run);cat.CatShout += new CatShoutEventHandler(JackMouse.run);cat.shout();}運(yùn)行結(jié)果:
I am cat tom. Cat is coming,JerryMouse run! Cat is coming,JackMouse run!幾點(diǎn)說明:
1、
new CatShoutEventHandler(JerryMouse.run)的含義是實(shí)例化一個(gè)委托,而委托的實(shí)例其實(shí)就是Mouse的run()方法;
2、
cat.CatShout +=表示
cat.add_CatShout(new CatShoutEventHandler(JerryMouse.run));“+=”就是增加委托實(shí)例對象的意思;”-=”就是移除委托實(shí)例對象的意思add_CatShout();使用它就等于減少一個(gè)需要觸發(fā)事件時(shí)通過的對象。
總結(jié)
- 上一篇: 大话设计模式—建造者模式
- 下一篇: 【定时任务】quartz表达式Cron