觀察者模式(Observer):定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
UML類圖:
分析:
Observer類,抽象觀察者,為所有的具體觀察者定義一個接口,在得到主題的通知時,更新自己這個接口叫做更新接口。抽象觀察者一般用一個抽象類或者一個接口實現。更新接口通常包含一個 Update方法,這個方法叫做更新方法。
Subject類,可翻譯為主題或者抽象通知者,一般用一個抽象類或者一個接口實現。它把所有對觀察者對象的引用,保存在一個聚集裡,每個主題都可以有任意數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。
ConcreteSubject類叫做具體主題或者具體通知者,將有關狀態存入具體觀察者對象:在具體主題的內部狀態得到改變時,給所有登記過的觀察者發出通知。具體主題通常用一個具體子類實現。
ConcreteObserver類,具體觀察者,實現抽象觀察者角色所要求的更新接口。以便使本身的狀態與主題的狀態相協調。具體觀察者角色可以保存一個指向具體主題對象的引用,具體 觀察者角色通常由一個具體子類實現。
觀察者模式(Observer)實現:
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Observer
{
/*
* Observer類,抽象觀察者,為所有的具體觀察者定義一個接口,在得到主題的通知時,更新自己
* 這個接口叫做更新接口。抽象觀察者一般用一個抽象類或者一個接口實現。更新接口通常包含一個
* Update方法,這個方法叫做更新方法。
*/
abstract class Observer
{
public abstract void Update();
}
/*
* Subject類,可翻譯為主題或者抽象通知者,一般用一個抽象類或者一個接口實現。
* 它把所有對觀察者對象的引用,保存在一個聚集裡,每個主題都可以有任意數量的觀察者。
* 抽象主題提供一個接口,可以增加和刪除觀察者對象。
*/
abstract class Subject
{
private List<Observer> observers = new List<Observer>();
//增加觀察者
public void Attach(Observer observer)
{
observers.Add(observer);
}
//移除觀察者
public void Detach(Observer observer)
{
observers.Remove(observer);
}
//通知
public void Notify()
{
foreach(Observer o in observers)
{
o.Update();//通知到每一個觀察者,使得每一個觀察者修改自身狀態
}
}
}
/*
* ConcreteSubject類叫做具體主題或者具體通知者,將有關狀態存入具體觀察者對象:
* 在具體主題的內部狀態得到改變時,給所有登記過的觀察者發出通知。具體主題通常
* 用一個具體子類實現。
*/
class ConcreteSubject : Subject
{
private string subjectState;
public string getSubjectState()
{
return this.subjectState;
}
public void setSubjectState(string state)
{
this.subjectState = state;
}
}
/*
* ConcreteObserver類,具體觀察者,實現抽象觀察者角色所要求的更新接口。以便使本身
* 的狀態與主題的狀態相協調。具體觀察者角色可以保存一個指向具體主題對象的引用,具體
* 觀察者角色通常由一個具體子類實現。
*/
class ConcreteObserver : Observer
{
private string name;
private string observerState;
private ConcreteSubject cSubject;
public ConcreteObserver(ConcreteSubject cSubject,string name)
{
this.cSubject = cSubject;
this.name = name;
}
public ConcreteSubject getCSubject()
{
return this.cSubject;
}
public void setCSubject(ConcreteSubject cSubject)
{
this.cSubject = cSubject;
}
public override void Update()
{
this.observerState = this.cSubject.getSubjectState();
Console.WriteLine("觀察者{0}的狀態是{1}",this.name,this.observerState);
//throw new NotImplementedException();
}
}
}
客戶端:
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Observer
{
//客戶端代碼
class Program
{
static void Main(string[] args)
{
ConcreteSubject cSubject = new ConcreteSubject();
cSubject.Attach(new ConcreteObserver(cSubject,"X"));
cSubject.Attach(new ConcreteObserver(cSubject,"Y"));
cSubject.Attach(new ConcreteObserver(cSubject,"Z"));
cSubject.setSubjectState("ABC");
cSubject.Notify();
Console.Read();
}
}
}
觀察者模式總結:
我們知道將一個系統分割成一系列相互協作的類有一個很不好的副作用,那就是需要維護相關對象間的一致性。我們不希望為了維護一致性而使各類緊密耦合,這樣會給維護、擴展和重用都帶來不便。而觀察者模式的關鍵對象是主題Subject和觀察者Observer,一個Subject可以有任意數量依賴它的Observer,一旦Subject的狀態發生了變化,所有的Observer都可以得到通知。Subject發出通知時,並不需要知道誰是它的觀察者,也就是說,具體觀察者是誰,它根本不需要知道。而任何一個具體觀察者不知道也不需要知道其他觀察者的存在。
當一個對象的改變需要同時改變其他對象,而且它不知道有多少對象待改變時,應該考慮使用觀察者模式。
總的來說,觀察者模式所做的工作其實就是在解除耦合。讓耦合的雙方都依賴於抽象而不是依賴於具體。從而使得各自的變化都不會影響另一邊的變化。