using System;
using System.Collections.Generic;
using System.Text;
//一、 觀察者模式
//目的
//概述
//原理
//二、 C#中的觀察者模式
//概述
//模型與觀察者基類
//優點
//三、 事例
//題目:貓大叫,兩隻老鼠開始逃跑,主人醒來,寶寶也醒來了並且哭了起來
//解決方案:
//1. 建立模型(目標基類)
//2. 建立觀察者基類(單行爲,多行爲)
//3. 建立具體目標
//4. 建立具體觀察者
//5. 運行測試
//一、 觀察者模式
//目的
//我們都知道解決一個問題有N種解決方式,但在面向對象的設計中如何能做到“高內聚,低耦合”,設計可重用的對象纔是我們追求的。在設計過程中,我們經常會接觸到一種情況:一個對象的行爲引發其它多個對象相應的行爲。這時我們便可以通過觀察者模式的設計思想來設計對象模型。
//概述
//觀察者模式(Observer Pattern)是設計模式中行爲模式的一種,它解決了上述具有一對多依賴關係的對象的重用問題。此模式的參與者分爲兩大類,一類是被觀察的目標,另一類是觀察該目標的觀察者們。正因爲該模式是基於“一對多”的關係,所以該模式一般是應用於由一個目標對象和N個觀察者對象組成(當然也可以擴展爲有多個目標對象,但我們現在只討論前者)的場合。當目標對象的狀態發生改變或做出某種行爲時,正在觀察該目標對象的觀察者們將自動地、連鎖地作出相應的響應行爲。
//原理
//我們可以把觀察目標理解爲主動方、發佈方、主體等;把觀察者理解爲被動方、訂閱方、觀察器等。目標是整個行爲鏈的源頭,其它觀察者都依賴於它的變化而作出響應。爲了實現低耦合,我們不能使用“直接調用”的方式而需要利用“訂閱(清單)-通知”的機制去完成設計。通俗地說就是觀察者向目標“訂閱”它的改變,而目標發生改變後就“通知”所有已經“訂閱”了它的改變的觀察者,從而執行“訂閱”的內容。這種機制的好處在於降低耦合度,分工明確,目標只負責在自身狀態發生改變或做出某種行爲時向自身的訂閱清單發出“通知”,而不是直接調用觀察者的行爲(方法);觀察者只負責向目標“訂閱”它的變化,以及定義自身在收到目標“通知”後所需要做出的具體行爲(也就是訂閱的內容)。就像我們向出版社訂閱報刊一樣,出版社有新一期報刊發行時並不是直接跟每位訂閱者聯繫,而是“通知”訂閱者名單按順序給每位訂閱者發送所訂報刊。
//二、 C#中的觀察者模式
//概述
//每種編程架構及程序語言,對觀察者模式都有不通的具體實現。在.NET框架中,C#語言使用委託以及事件,可以很好的實現觀察者模式。委託相當於“訂閱清單”的角色,當目標中關聯了該委託的事件被觸發時,則委託將自動按序執行觀察者註冊於委託中的方法。
//模型與觀察者基類
//我們把觀察者模式的參與者都描述爲派生自模型及觀察者二個抽象基類的類。模型規劃了事件,而觀察者則規劃了訂閱及行爲。
//模型需要做的只是聲明委託以及聲明委託類型的事件。當然,還可以附加上封裝了觸發委託事件的方法。所有派生自模型的類都是具體目標,它們所要做的只是在適當的場合觸發事件。(即發出“通知”)。
//在觀察者基類中,我們通過構造器將抽象的響應方法註冊(訂閱)於委託事件中。所有派生自觀察者基類的類都是具體觀察者。因爲訂閱行爲已經在抽象基類完成,具體觀察者需要做的只是通過覆蓋觀察者基類的方法去定義具體需要響應的行爲,和通過構造器把需要觀察的具體目標傳遞給基類構造器。
//優點
//通過對模型與觀察者基類的分析可知,委託與事件的機制幾乎消除了這兩個模塊之間的耦合,靈活性提高了很多。如果需要增加觀察者,則只需要覆蓋基類抽象方法及把觀察目標傳遞給基類。
//三、 事例
//題目:貓大叫,兩隻老鼠開始逃跑,主人醒來,寶寶也醒來了並且哭了起來.
namespace Observer
{
class Program
{
public abstract class ModelBase
{
public ModelBase()
{
}
//聲明一個委託,用於代理一系列“無返回”及“不帶參”的自定義方法
public delegate void SubEventHandler();
//聲明一個綁定上行所定義委託的事件
public event SubEventHandler SubEvent;
/// 封裝了觸發事件的方法
/// 主要爲了規範化及安全性,除觀察者基類外,其派生類不直接觸發委託事件
protected void Notify()
{
if (this.SubEvent != null)
this.SubEvent();
}
}
public abstract class Observer
{
public Observer(ModelBase childModel)
{
childModel.SubEvent += new ModelBase.SubEventHandler(Response);
}
public abstract void Response();
}
public class Cat : ModelBase
{
public Cat()
{ }
public void cry()
{
System.Console.WriteLine("Cat Cry...");
this.Notify();
}
}
public class Mouse: Observer
{
public Mouse(ModelBase childmodel)
: base(childmodel)
{ }
public override void Response()
{
System.Console.WriteLine("老鼠開始跑");
}
}
public class Master : Observer
{
public Master (ModelBase childmodel)
: base(childmodel)
{ }
public override void Response()
{
System.Console.WriteLine("主人醒來");
}
}
public class Baby : Observer
{
public Baby(ModelBase childmodel)
: base(childmodel)
{ }
public override void Response()
{
System.Console.WriteLine("baby醒來");
}
}
public static void Main(string[] args)
{
Cat cat = new Cat();
Mouse mouse = new Mouse(cat);
Baby baby = new Baby(cat);
Master master = new Master(cat );
cat.cry();
}
}
}