C#實(shí)現(xiàn)觀察者模式(Observer?Pattern)的兩種方式
在觀察者模式中有2個(gè)要素:一個(gè)是被觀察對(duì)象,另一個(gè)是觀察者。但被觀察對(duì)象的狀態(tài)發(fā)生改變會(huì)通知觀察者。
舉例:把訂閱報(bào)紙的人看作是觀察者,把報(bào)紙看作被觀察對(duì)象。每當(dāng)有新的新聞就要通知訂閱報(bào)紙的人。本篇分別用實(shí)現(xiàn)接口和使用委托事件的方式來(lái)實(shí)現(xiàn)。
通過(guò)實(shí)現(xiàn)接口實(shí)現(xiàn)
觀察者接口,把接收到的新聞顯示出來(lái)。
public interface IObserver
{
void Update(string news);
}被觀察對(duì)象接口,提供3個(gè)方法:注冊(cè)觀察者,取消觀察者,通知觀察者。
public interface ISubject
{
void RegisteerObserver(IObserver o);
void RemoveObserver(IObserver o);
void NotifyObservers();
}被觀察對(duì)象實(shí)現(xiàn)類(lèi),維護(hù)著一個(gè)觀察者接口的集合,對(duì)觀察者的注冊(cè)和取消實(shí)際上是往這個(gè)集合添加或移除數(shù)據(jù)。
public class NewsPublisher : ISubject
{
private List<IObserver> observers = new List<IObserver>();
private List<string> newsList = new List<string>();
public void RegisteerObserver(IObserver o)
{
observers.Add(o);
}
public void RemoveObserver(IObserver o)
{
observers.Remove(o);
}
public void NotifyObservers()
{
foreach (IObserver o in observers)
{
o.Update(newsList[newsList.Count - 1]);
}
}
public void PublishNews(string news)
{
newsList.Add(news);
NotifyObservers();
}
}另外,被觀察對(duì)象實(shí)現(xiàn)類(lèi)還維護(hù)著一個(gè)string類(lèi)型的新聞集合,每當(dāng)發(fā)布新聞,就往這個(gè)集合里添加數(shù)據(jù),并通知所有的注冊(cè)觀察者。
觀察者的實(shí)現(xiàn)類(lèi)。
public class NewsSubscriber : IObserver
{
public void Update(string news)
{
Console.WriteLine("收到通知了");
Console.WriteLine(news);
}
}客戶(hù)端,被觀察對(duì)象注冊(cè)觀察者并觸發(fā)動(dòng)作。
class Program
{
static void Main(string[] args)
{
NewsPublisher publisher = new NewsPublisher();
NewsSubscriber subscriber = new NewsSubscriber();
publisher.RegisteerObserver(subscriber);
publisher.PublishNews("看報(bào),看報(bào),快來(lái)看報(bào)~");
Console.ReadKey();
}
}
使用委托事件實(shí)現(xiàn)
看到以上的做法,委托和事件這對(duì)好朋友就笑了。注冊(cè)、取消觀察者還得用2個(gè)方法,那讓我們情何以堪?我們這樣做:
觀察者類(lèi)只負(fù)責(zé)對(duì)收到的新聞顯示。
public class NewsSubscriber
{
public void Update(string news)
{
Console.WriteLine("收到新聞了~");
Console.WriteLine(news);
}
}被觀察對(duì)象類(lèi)用到了委托和事件。
public class NewsPublisher
{
private readonly List<string> newsList = new List<string>();
public delegate void NotifyOvserversHandler(string news);
public event NotifyOvserversHandler newsPublished;
public void PublishNews(string news)
{
newsList.Add(news);
newsPublished(newsList[newsList.Count - 1]);
}
}以上,委托聲明了方法的定義,接收一個(gè)string類(lèi)型參數(shù),返回void。事件負(fù)責(zé)對(duì)符合委托定義的、觀察者方法的注冊(cè)和取消。
在客戶(hù)端使用事件對(duì)方法進(jìn)行注冊(cè)。
class Program
{
static void Main(string[] args)
{
NewsPublisher publisher = new NewsPublisher();
NewsSubscriber subscriber = new NewsSubscriber();
publisher.newsPublished += subscriber.Update;
publisher.PublishNews("現(xiàn)在是看報(bào)時(shí)間~");
Console.ReadKey();
}
}與通過(guò)接口實(shí)現(xiàn)不同,使用事件注冊(cè)的是觀察者的方法,而不是觀察者本身。

總結(jié):無(wú)論通過(guò)接口實(shí)現(xiàn),還是使用委托和事件,觀察者模式的要素是不變的:被觀察對(duì)象,觀察者,被觀察者提供注冊(cè)、取消觀察者或觀察者方法,通過(guò)被觀察對(duì)象的某個(gè)方法觸發(fā)、通知觀察者。
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
Unity實(shí)現(xiàn)引導(dǎo)頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)引導(dǎo)頁(yè)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
Unity中的PostProcessScene實(shí)用案例深入解析
這篇文章主要為大家介紹了Unity中的PostProcessScene實(shí)用案例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
C# XML與Json之間相互轉(zhuǎn)換實(shí)例詳解
這篇文章主要介紹了C# XML與Json之間相互轉(zhuǎn)換實(shí)例詳解,大家參考使用吧2013-11-11
C# 抽象類(lèi),抽象屬性,抽象方法(實(shí)例講解)
下面小編就為大家分享一篇C# 抽象類(lèi),抽象屬性,抽象方法的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
C#中實(shí)現(xiàn)Fluent Interface的三種方法
這篇文章主要介紹了C#中實(shí)現(xiàn)Fluent Interface的三種方法,本文講解了Fluent Interface的簡(jiǎn)單實(shí)現(xiàn)、使用裝飾器模式和擴(kuò)展方法實(shí)現(xiàn)Fluent Interface等3種實(shí)現(xiàn)方法,需要的朋友可以參考下2015-03-03

