設計模式之觀察者模式與事件委托
觀察者模式:
定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自己更新自己。
觀察者結構模式圖:
結合例子:
static void Main(string[] args) { //老板dandan Boss dandan=new Boss (); //看股票的同事 StockObserver hongjie=new StockObserver ("張三",dandan ); dandan.Attach (hongjie ); //老板回來 dandan .SubjectState="丹丹回來了"; //發出通知 dandan.Notify (); } //通知者接口 interface Subject { void Attach(Observer observer); void Detach(Observer observer); void Notify(); string SubjectState { get; set; } } //具體通知者類 class Boss:Subject { //同事列表 private IList<Observer > observers=new List<Observer>(); private string action; //增加 public void Attach(Observer observer) { observers.Add (observer ); } //減少 public void Detach(Observer observer) { observers.Remove (observer ); } //通知 public void Notify() { foreach (Observer o in observers ) o.Update (); } //老板狀態 public string SubjectState { get {return action ;} set {action =value ;} } } //抽象觀察者 abstract class Observer { protected string name; protected Subject sub; public Observer (string name,Subject sub) { this.name =name ; this.sub =sub ; } public abstract void Update(); } class StockObserver:Observer { public StockObserver (string name,Subject sub):base(name,sub ) { } public override void Update() { Console .WriteLine ("{0}{1}關閉股票行情,繼續工作!",sub.SubjectState ,name ); } }這裏用到了一個接口Subject和一個抽象類Observer,這兩個抽象類的使用體現了麵向對象的思想,減少了觀察者與被觀察者之間的耦合度,如果我們直接寫出公司中的boss(被觀察者)和observer(觀察者),那麼他們之間必然會有緊密的聯係,如果被觀察者改變或增加,不管被觀察者類會受到影響,由於被觀察者與觀察者之間的緊耦合,則,觀察者也必然會做相應修改,這不符合依賴倒轉原則和開閉原則。因此,我們需要用觀察者模式,一方麵,觀察者模式具有一個對象的改變可以同時改變其他所有對象;另一方麵,觀察者模式運用接口和抽象類,降低了耦合度,符合設計原則,增強了程序的可維護、擴展和重用性。
但這一設計模式仍然有其缺點,因為這種模式的一個特點是抽象通知類還是依賴抽象觀察類的,如果沒有抽象觀察類,那麼通知就無法實現,所以為了避免這一不足,我們就用到了委托事件。
事件委托與觀察者模式:
在之前的博客中,我已經講到了委托,何謂委托?簡單的說委托可以看做是對函數的抽象,是函數的類,委托的實例將代表一個實例,一旦為委托分配了方法,委托將與該方法具有完全相同的行為。在沒有抽像觀察類的情況下,我們可以通過使用事件委托,將同一通知發給所有通知者,即時沒有接口,這一功能同樣可以實現,而且降低了與抽象通知類之間的依賴關係,增加了擴展性、靈活性。
觀察者模式的幾個要點:
1、使用麵向對象的抽象,觀察者模式使得我們可以獨立改變目標與觀察者,從而使得兩者之間的依賴關係達到鬆耦合
2、目標發送通知時,無需指定觀察者,通知會自動傳播。觀察者自己決定是否需要訂閱通知,目標對象對此一無所知。
3、委托充當了抽象的觀察者接口,而提供事件的對象充當餓了目標對象。委托是比抽象觀察者接口更為鬆耦合的設計。
最後更新:2017-04-03 12:55:06