新聞中心
在現(xiàn)實(shí)世界中,許多對象并不是獨(dú)立存在的,其中一個對象的行為發(fā)生改變可能會導(dǎo)致一個或者多個其他對象的行為也發(fā)生改變。例如,某種商品的物價上漲時會導(dǎo)致部分商家高興,而消費(fèi)者傷心;還有,當(dāng)我們開車到交叉路口時,遇到紅燈會停,遇到綠燈會行。這樣的例子還有很多,例如,股票價格與股民、微信公眾號與微信用戶、氣象局的天氣預(yù)報與聽眾、小偷與警察等。

在軟件世界也是這樣,例如,Excel 中的數(shù)據(jù)與折線圖、餅狀圖、柱狀圖之間的關(guān)系;MVC 模式中的模型與視圖的關(guān)系;事件模型中的事件源與事件處理者。所有這些,如果用觀察者模式來實(shí)現(xiàn)就非常方便。
使用場景
觀察者模式所做的工作其實(shí)就是在解耦,讓耦合的雙方都依賴于抽象而不是具體,從而使得各自的變化都不會影響另一邊的變化。
當(dāng)一個對象的改變需要改變其他對象的時候,而且它不知道具體有多少對象有待改變的時候,應(yīng)該考慮使用觀察者模式。
一個抽象模型有兩方面,其中一方面依賴于另一方面,這時用觀察者模式可以將這兩者封裝在獨(dú)立的對象中使得他們各自獨(dú)立地改變和復(fù)用。
舉例
public interface ISubject
{
void Notify();
string SubjectState { get; set; }
}
public class Boss : ISubject
{
private readonly IList _observers = new List();
public void Attach(Observer observer)
{
_observers.Add(observer);
}
public void Detach(Observer observer)
{
_observers.Remove(observer);
}
public void Notify()
{
foreach (var observer in _observers)
{
observer.Update();
}
}
public string SubjectState { get; set; }
}
public abstract class Observer
{
protected string Name;
protected ISubject Subject;
protected Observer(string name, ISubject subject)
{
Name = name;
Subject = subject;
}
public abstract void Update();
}
public class StockObserver : Observer
{
public StockObserver(string name, ISubject subject) : base(name, subject)
{
}
public override void Update()
{
Console.WriteLine($"{Name} {Subject.SubjectState} 關(guān)閉股票行情,繼續(xù)工作");
}
}
public class NBAObserver : Observer
{
public NBAObserver(string name, ISubject subject) : base(name, subject)
{
}
public override void Update()
{
Console.WriteLine($"{Name} {Subject.SubjectState} 關(guān)閉 NBA 直播,繼續(xù)工作");
}
}
var boss = new Boss();
var stockObserver = new StockObserver("魏關(guān)姹", boss);
var nbaObserver = new NBAObserver("易管查", boss);
boss.Attach(stockObserver);
boss.Attach(nbaObserver);
boss.Detach(stockObserver);
boss.SubjectState = "老板我胡漢三回來了";
boss.Notify();
借助 event(委托) 我們可以實(shí)現(xiàn)可以靈活的觀察者模式,我們定義了一個新老板來演示事件的方式,來看下面的示例:
public class NewBoss : ISubject
{
public event Action Update;
public void Notify()
{
Update?.Invoke();
}
public string SubjectState { get; set; }
}
public class GamePlayerObserver
{
private readonly string _name;
private readonly ISubject _subject;
public GamePlayerObserver(string name, ISubject subject)
{
_name = name;
_subject = subject;
}
public void CloseGame()
{
Console.WriteLine($"{_name} {_subject.SubjectState} 關(guān)閉 LOL 游戲,繼續(xù)工作");
}
}
var newBoss = new NewBoss();
var stockObserver = new StockObserver("魏關(guān)姹", boss);
var nbaObserver = new NBAObserver("易管查", boss);
var gameObserver = new GamePlayerObserver("西門", newBoss);
// 注冊通知事件
newBoss.Update += stockObserver.Update;
newBoss.Update += nbaObserver.Update;
newBoss.Update += gameObserver.CloseGame;
newBoss.Update -= stockObserver.Update;
newBoss.SubjectState = "老板我胡漢三回來了";
newBoss.Notify();
從上面這個示例可以看到,通過事件的方式,我們可以不要求顯示繼承于 Observer 這個抽象類,可以更加靈活,擴(kuò)展性更強(qiáng),這也是很多類庫中會使用事件來擴(kuò)展的重要原因
More
設(shè)計模式要干的事情就是解耦。創(chuàng)建型模式是將創(chuàng)建和使用代碼解耦,結(jié)構(gòu)型模式是將不同功能代碼解耦,行為型模式是將不同的行為代碼解耦,具體到觀察者模式,它是將觀察者和被觀察者代碼解耦。
根據(jù)應(yīng)用場景的不同,觀察者模式會對應(yīng)不同的代碼實(shí)現(xiàn)方式:有同步阻塞的實(shí)現(xiàn)方式,也有異步非阻塞的實(shí)現(xiàn)方式;有進(jìn)程內(nèi)的實(shí)現(xiàn)方式,也有跨進(jìn)程的實(shí)現(xiàn)方式。
在對象之間定義一個一對多的依賴,當(dāng)一個對象狀態(tài)改變的時候,所有依賴的對象都會自動收到通知。一般情況下,被依賴的對象叫作被觀察者(Observable),依賴的對象叫作觀察者(Observer)。不過,在實(shí)際的項目開發(fā)中,這兩種對象的稱呼是比較靈活的,有各種不同的叫法,比如:Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener。不管怎么稱呼,只要應(yīng)用場景符合剛剛給出的定義,都可以看作觀察者模式。
EventBus(事件總線) 就是一個觀察者模式的實(shí)際應(yīng)用。
分享名稱:詳解觀察者模式
網(wǎng)址分享:http://m.fisionsoft.com.cn/article/djheegd.html


咨詢
建站咨詢
