前言
今天我們一起看看這個觀察者模式,這個模式簡單來說就是一個發布訂閱類似的模式,按照名字來理解也就是存在一個觀察者和一個被觀察者,說幾個例子給大家聽,大家應該就明白了,例如在我們現在通過銀行卡支付之后,會收到銀行發過來的提示資訊,例如當我們話費余額或者流量不足之時也會收到提示資訊,這其中的邏輯幫我們理解觀察者模式,當我們觀察的一個物件發送變化之時就會觸發某一機制,然后做出一系列的措施,
觀察者模式介紹
一、來由
在軟體系統中我們經常會遇到物件之間存在一對多的關系,當一個物件被修改時,將會自動通知其依賴的物件,當然如果這些依賴關系過于緊密對于系統來說又不好抵御其變化,所以我們又需要實作其結構的松耦合,
二、意圖
定義物件間的一種一對多的依賴關系,當一個物件的狀態發生改變時,所有依賴于它的物件都得到通知并被自動更新,
三、案例圖

四、觀察者代碼示例
看上面的案例圖、我們來細細說下這其中的四種角色:
抽象主題角色:將所有的觀察者參考保存在一個串列,同時包含增加洗掉觀察者的操作,包含呼叫抽象觀察者的操作方法,
具體主題角色:實作其抽象主題的抽象方法,
抽象觀察者:為所有的具體觀察者定義一個介面,在得到主題通知時更新自己,
具體觀察者:實作抽象觀察者定義的介面,是自身的狀態與主題的狀態相對應,
到這里我們簡單的介紹了下觀察這模式的原理,我們接下來使用手機話費不足時短信提醒這一個案例來講述觀察者模式的代碼示例吧,當我們手機話費低于或小于10元的時候,將會觸發變化更新提示:
namespace Observer_Pattern{ class ObserverPattern { } /// <summary> /// 抽象主題角色(將所有觀察者物件的參考保存在一個串列中、含有增加和洗掉觀察者物件操作、包含呼叫抽象觀察者的變更操作) /// </summary> public abstract class Subject { internal List<Observer> observers ; internal int Balance; /// <summary> /// 保存所有觀察者物件 /// </summary> public Subject(int balance) { observers = new List<Observer>(); Balance = balance; } /// <summary> /// 增加觀察者物件 /// </summary> public abstract void Adds(Observer observer); /// <summary> /// 洗掉觀察者物件 /// </summary> public abstract void Removes(Observer observer); /// <summary> /// 通知觀察者變化 /// </summary> public void Notice() { foreach (var item in observers) { if (item!=null) { item.Change(this); } } } } /// <summary> /// 抽象觀察者(為所有具體觀察者提供了一個當主題通知是變更自己的操作) /// </summary> public abstract class Observer { public abstract void Change(Subject Item); } /// <summary> /// 具體主題角色,實作抽象角色抽象方法 /// </summary> public class CallChargeSubject : Subject { public CallChargeSubject( int balance) : base( balance ) { } public override void Adds(Observer observer) { observers.Add(observer); } public override void Removes(Observer observer) { observers.Remove(observer); } } /// <summary> /// 具體觀察者 /// </summary> public class CallChargeObserver : Observer { internal string Name; public CallChargeObserver(string name) { Name = name; } public override void Change(Subject Item) { Console.WriteLine($"{Name}您好,您當前話費余額為:{Item.Balance},為了避免后續為您帶來不便請及時充值!"); } }}
namespace Observer_Pattern{ class Program { static void Main(string[] args) { Subject subject = new CallChargeSubject(10); subject.Adds(new CallChargeObserver("張三")); subject.Adds(new CallChargeObserver("李四")); subject.Notice(); } }}
使用場景及優缺點
一、使用場景
1、一個抽象模型有兩個方面,其中一個方面依賴于另一個方面,將這些方面封裝在獨立的物件中使它們可以各自獨立地改變和復用
2、當對一個物件的改變需要同時做出改變的時候,而又不知道具體有多少物件需要待改變的情況下,
3、一個物件必須通知其他物件,但是并不知道這些物件是誰,
二、優點
1、觀察者和被觀察者直接松耦合,依賴于抽象而不是具體實作
2、建立了一套觸發的訂閱發布機制,
三、缺點
1、如果一個被觀察者有很多觀察者的話,變化通知所有觀察者需要花費很多的時間
2、觀察者和被觀察者之間有回圈依賴的話,變化觸發之后會造成回圈呼叫,會導致系統崩潰,
3、觀察者只知道被觀察者發生了變化,但是并不知道被觀察者是如何發生變化的,
總結
到這里我們就介紹完了觀察者模式,這個模式是一種一對多的關系依賴,如果不使用抽象主題角色和抽象觀察者也是可以實作監控話費的任務的,但是這樣會造成主題角色和觀察者角色緊耦合,觀察者模式主要實作的就是解耦代碼,實作依賴倒置原則,依賴于抽象而不是具體實作,再說觀察者模式、在我前面的文章又寫過委托與事件,其中提到了事件基于委托,為委托提供了一種發布/訂閱機制,我們仔細研究可以發現觀察者模式和委托還是較為相似的,
這個社會是存在不公平的,不要抱怨,因為沒有用!人總是在反省中進步的!
C#設計模式系列目錄
歡迎大家掃描下方二維碼,和我一起踏上設計模式的闖關之路吧!

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/39947.html
標籤:設計模式
上一篇:設計模式-行為型-解釋器模式
