什麼是觀察者模式?
摘自百度百科的說法:觀察者模式(有時又被稱為發布(publish )-訂閱(Subscribe)模式、模型-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟件設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。
說白了,就是一個主題,可以有N多個觀察者,一個觀察者,也可以訂閱N多個主題。當一個主題,發生改變時,會通知訂閱它的觀察者,觀察者收到通知後,可以做相應的處理。觀察者模式,是軟件設計模式中的一種。接下裡,我們介紹下,使用C#實現的觀察者模式。附上代碼。
首先,我們新建一個名為AppObserver的控制台項目。結構如下:
Strategy目錄下新建兩個接口,一個IObserver(觀察者)、一個ISubject(主題)。讓我們看看,這兩個接口分別定義了什麼?
/*
* Created by http://www.lichaoqiang.com
* User: 李朝強
* Date: 2016/9/2
* Time: 16:25
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
namespace AppObserver.Strategy
{
/// <summary>
/// Description of ISubject.
/// </summary>
public interface ISubject
{
/// <summary>
/// 主題
/// </summary>
string Title{get;set;}
/// <summary>
/// 觀察者
/// </summary>
List<IObserver> Observers{get;}
/// <summary>
/// 添加訂閱
/// </summary>
/// <param name="observer"></param>
void AddObserver(IObserver observer);
/// <summary>
/// 發布
/// </summary>
void Publish();
}
}
觀察者接口(IObserver):
/*
* Created by http://www.lichaoqiang.com
* User: 李朝強
* Date: 2016/9/2
* Time: 16:27
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
namespace AppObserver.Strategy
{
/// <summary>
/// Description of IObserver.
/// </summary>
public interface IObserver
{
/// <summary>
/// 名稱
/// </summary>
string Name{get;}
/// <summary>
/// 主題
/// </summary>
List<ISubject> Subjects{get;}
/// <summary>
/// 通知
/// </summary>
void Notify(ISubject subject);
/// <summary>
/// 訂閱
/// </summary>
/// <param name="subject"></param>
void Subscribe(ISubject subject);
/// <summary>
/// 取消訂閱
/// </summary>
/// <param name="subject"></param>
void Unsubscribe(ISubject subject);
}
}
接下來,新建一個Support文件夾,提供對以上兩個接口的實現。具體代碼如下:
主題:
/*
* Created by http://www.lichaoqiang.com
* User: 李朝強
* Date: 2016/9/2
* Time: 16:34
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using AppObserver.Strategy;
namespace AppObserver.Support
{
/// <summary>
/// Description of Subject.
/// </summary>
public class Subject:ISubject
{
/// <summary>
/// 構造函數
/// </summary>
public Subject()
{
Observers = new List<IObserver>();
}
#region ISubject implementation
/// <summary>
/// 添加觀察者
/// </summary>
/// <param name="observer"></param>
void ISubject.AddObserver(IObserver observer)
{
Observers.Add(observer);
}
/// <summary>
/// 發布
/// </summary>
void ISubject.Publish()
{
if (null != Observers && Observers.Count > 0)
foreach (var item in Observers) {item.Notify(this);}
}
/// <summary>
/// 主題
/// </summary>
string ISubject.Title {
get;
set;
}
/// <summary>
/// 觀察者
/// </summary>
public List<IObserver> Observers { get; private set; }
#endregion
}
}
觀察者:
/*
* Created by http://www.lichaoqiang.com
* User: 李朝強
* Date: 2016/9/2
* Time: 16:37
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using AppObserver.Strategy;
namespace AppObserver.Support
{
/// <summary>
/// 觀察者
/// </summary>
public class Observer:IObserver
{
/// <summary>
/// 構造函數
/// </summary>
public Observer()
{
Subjects = new List<ISubject>();
}
/// <summary>
/// 構造函數
/// </summary>
/// <param name="name"></param>
public Observer(String name)
: this()
{
Name = name;
}
#region IObserver implementation
/// <summary>
/// 名字
/// </summary>
public string Name{ get; private set; }
/// <summary>
/// 通知
/// </summary>
void IObserver.Notify(ISubject subject)
{
//這裡具體可以處理你的業務邏輯
//我們可以通過擴展suject對象,來傳遞信息
Console.WriteLine("【{0}】收到最新通知(Notify)主題:{1}", this.Name, subject.Title);
}
/// <summary>
/// 訂閱
/// </summary>
/// <param name="subject">主題</param>
void IObserver.Subscribe(ISubject subject)
{
subject.AddObserver(this);
Subjects.Add(subject);
}
/// <summary>
/// 取消訂閱
/// </summary>
/// <param name="subject">主題</param>
void IObserver.Unsubscribe(ISubject subject)
{
}
/// <summary>
///獲取已訂閱的主題
/// </summary>
public List<ISubject> Subjects { get; private set; }
#endregion
}
}
完成以上幾步,就簡單的實現了觀察者模式。讓我們一起來看看效果吧。
場景:張三和李四兩個人,一個愛好體育和娛樂,一個愛好體育。於是,張三,拿起IiPhone 6s plus,打開App,點擊並訂閱了《體育頻道》、《娛樂頻道》兩個欄目,李四看了,也馬上掏出小米5s,以迅雷不及掩耳盜鈴之勢,打開相同的APP,也同樣訂閱了《體育頻道》這檔欄目。就在這個時候,遠在千裡之外的一座大都市,一個S身材的MZ,坐在辦公桌前,准備好了資訊內容,准備這個時候,向廣大粉絲,推送這些信息。於是,她先把准備好的體育信息,標題為“張繼科XXXX”的主題,推送出去。然後,接著隔壁同事老王,負責《娛樂頻道》的有痣青年,把主題為《王寶強XXXX》的信息,推送出去。這個時候,張三和李四的手機,不約而同的響起了一聲清脆的聲音。打開一看,效果如下:
張三和李四,頓時沉迷其中,認認真真的閱讀起了這些內容。
張三、李四虛構故事,以娛大家,博君一笑,夫復何求哈。