標籤:設計模式 c# 委託 事件
在一口一個設計模式--觀察者模式中,我們已經知道如何應用觀察者模式,但通過最近的深入學習,發現觀察者模式存在以下缺陷:
1.抽象通知者依賴於抽象觀察者;
2.每個具體觀察者被調用的方法必須一致。
比如在機房收費系統中關於觀察者模式的應用如所示:
這個設計存在以下問題:
1.抽象通知者需要把抽象觀察者中的所有具體對象添加到集合中,以備向每個具體觀察者發送通知訊息;
2.在發送通知訊息時,具體觀察者中被通知的方法必須一致,否則具體通知者無法完成遍曆;
3.更新卡內餘額、更新學生上機狀態和儲存學生上機記錄這三個類沒什麼相同的地方,抽象出來的抽象觀察者有點牽強。
經過苦苦的思索,我發現用C#中的委託和事件機制解決上述問題,代碼結構如下:
抽象通知者:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 觀察者模式_委託{ public interface Informer { void Notify(); string Action { get; set; } }}
具體通知者--正常下機:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 觀察者模式_委託{ public class Down : Informer { //聲明一個委託 public delegate void EventHandler(); //為委託EventHandler添加事件Update public event EventHandler Update; public void Notify() { this.Update(); } private string action; public string Action { get { return action; } set { action = value; } } }}
具體通知者--強制下機:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 觀察者模式_委託{ public class ForceDown : Informer { //聲明一個委託 public delegate void EventHandler(); //為委託EventHandler添加事件Update public event EventHandler Update; public void Notify() { this.Update(); } private string action; public string Action { get { return action; } set { action = value; } } }}
這個我們不需要抽象觀察者,直接具體觀察者--更新卡內餘額:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 觀察者模式_委託{ public class UpdateBalance { protected Informer dn; public UpdateBalance(Informer dn) { this.dn = dn; } public void ModifyBalance() { Console.WriteLine("{0}!該卡要下機,更新喻額!", dn.Action); } }}
具體觀察者--更新學生上機狀態:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 觀察者模式_委託{ public class OffLine { protected Informer dn; public OffLine(Informer dn) { this.dn = dn; } public void DelOnlineInfo() { Console.WriteLine("{0}!該卡要下機,刪除正在上機表中的該卡資訊!", dn.Action); } }}
具體觀察者--儲存學生上機記錄:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 觀察者模式_委託{ public class SaveRec { protected Informer dn; public SaveRec(Informer dn) { this.dn = dn; } public void SaveLineRec() { Console.WriteLine("{0}!該卡要下機,儲存上機記錄資訊!", dn.Action); } }}
main方法:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 觀察者模式_委託{ class Program { static void Main(string[] args) { Down dn = new Down(); OffLine ol = new OffLine(dn); UpdateBalance up = new UpdateBalance(dn); SaveRec sr = new SaveRec(dn); dn.Update+=new Down.EventHandler(ol.DelOnlineInfo); dn.Update += new Down.EventHandler(up.ModifyBalance); dn.Update += new Down.EventHandler(sr.SaveLineRec); dn.Action = "刷卡下機"; dn.Notify(); } }}
程式執行結果如下所示:
通過執行結果,我們可以發現,在main方法中的正常下機事件dn.Update發生後,通過委託Down.EventHandler綁定到dn.Update事件上的三個方法ol.DelOnlineInfo、up.ModifyBalance、sr.SavelineRec都會被執行,達到觀察者模式的效果。
現在我們可以發現:抽象通知者不再依賴於抽象觀察者,因為抽象通知者通過委託通知具體觀察者;具體觀察者中被調用的方法也沒必要一致,因為只需把想要執行的方法綁定到事件上就行;具體通知者也不必存在共性,不必牽強的對這三個類進行抽象。委託+事件完美解決上述問題。