大話設計模式—觀察者模式
當物件間存在一對多關係時,則使用觀察者模式(Observer Pattern)。比如,當一個物件被修改時,則會自動通知它的依賴物件。觀察者模式屬於行為型模式。主要解決一個物件狀態改變給其他物件通知的問題,而且要考慮到易用和低耦合,保證高度的協作。
大話設計模式中程傑老師對觀察者模式的定義是,觀察者模式:定義物件間的一種一對多的依賴關係,讓多個觀察者物件同時監聽某一個主題物件。這個主題物件在狀態發生改變時,會通知所有觀察者物件,使它們能夠自動更新自己。
觀察者模式結構圖如下:
示例程式碼:
package com.dfcDemo.observer;
import java.util.ArrayList;
import java.util.List;
/**
* 抽象主題類或者抽象觀察者類,一般用一個抽象類或者一個介面實現,
* 它把所有對物件的引用儲存在一個集合中,每個主題都可以有任意數
* 量的觀察者
* @author lmb
*
*/
public abstract class Subject {
private List<Observer> observers = new ArrayList<Observer>();
//add observer
public void attach(Observer observer){
observers.add(observer);
}
//remove observer
public void detach(Observer observer){
observers.remove(observer);
}
//send notify to observers
public void sendNotify(){
for(Observer o : observers){
o.update();
}
}
}
package com.dfcDemo.observer;
/**
* 抽象觀察者類,為所有具體觀察者定義一個介面,在得到通知時更新自己
* @author lmb
*
*/
public abstract class Observer {
public abstract void update();
}
package com.dfcDemo.observer;
/**
* 具體通知者,將有關狀態存入具體觀察者物件;
* 在具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。
* 具體主題角色通常用一個具體子類實現
* @author lmb
*
*/
public class ConcreteSubject extends Subject{
private String subjectState;
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
}
}
package com.dfcDemo.observer;
/**
* 具體觀察者:實現抽象觀察者角色所要求的更新介面,已是本身狀態與主題狀態相協調
* @author lmb
*
*/
public class ConcreteObserver extends Observer{
private String observerState;
private ConcreteSubject subject;
public String name;
//constructor
public ConcreteObserver(ConcreteSubject subject, String name){
this.subject = subject;
this.name = name;
}
public ConcreteSubject subject(){
return subject;
}
@Override
public void update() {
observerState = subject.getSubjectState();
System.out.println("The observer's state of " + name + " is " + observerState);
}
}
package com.dfcDemo.observer;
public class TestObserver {
public static void main(String[] args) {
//build the object of subject
ConcreteSubject subject = new ConcreteSubject();
//add observer for the object of subject
subject.attach(new ConcreteObserver(subject,"observer Tom"));
subject.attach(new ConcreteObserver(subject,"observer Jerry"));
subject.attach(new ConcreteObserver(subject,"observer Jack"));
//set the state of subject
subject.setSubjectState("ready");
subject.sendNotify();
}
}
執行結果:
The observer's state of observer Tom is ready
The observer's state of observer Jerry is ready
The observer's state of observer Jack is ready
觀察者模式的特點:
將一個系統分割成一系列相互協作的類有一個很不好的副作用,那就是需要維護相關物件間的一致性。我們不希望為了維護一致性而使各類緊密耦合,這樣會給維護、擴充套件和重用都帶來不便。觀察者模式的關鍵物件是主題Subject和觀察者Observer,一個Subject可以有任意數目的依賴它的Observer,一旦Subject的狀態發生改變,所有的Observer都可以得到通知。Subject發出通知時並不需要知道誰是它的觀察者,也就是說,具體觀察者是誰它根本不需要知道。而任何一個具體觀察者不知道也不需要知道其他觀察者的存在。
使用場景:
1、當一個物件的改變需要同時改變其他物件,並且它不知道具體有多少物件有待改變時,應考慮使用觀察者模式;
2、一個抽象模型有兩個方面,其中一方面依賴與另一方面,這是觀察者模式可以將這兩者封裝在獨立的物件中是它們各自獨立地改變和複用。
總的來講,觀察者模式所做的工作其實就是在解除耦合,讓耦合的雙方都依賴於抽象,而不是依賴於具體,從而使得各自的變化都不會影響另一邊的變化。
優點
觀察者模式解除了主題和具體觀察者的耦合,讓耦合的雙方都依賴於抽象,而不是依賴具體。從而使得各自的變化都不會影響另一邊的變化。
缺點
依賴關係並未完全解除,抽象通知者依舊依賴抽象的觀察者。
改進
使用事件和委託來改進