觀察者模式定義了對象間的一種一對多依賴關系,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新。
它將觀察者和被觀察者的對象分離開。提高了應用程序的可維護性和重用性。
實現觀察者模式有很多形式,一種是“注冊---通知---撤銷注冊”的形式。
觀察者Observer:所有潛在的觀察者必須實現觀察者接口,這個接口只有update方法,當主題改變時,它被調用。
具體觀察者ConcreteObserver: 具體觀察者可以是任何實現了Observer接口的類。觀察者必須注冊具體主題,一邊接收更新。
可觀察者Subject: 主題接口,即可觀察者Observable,對象使用此接口注冊為觀察者,或者把自己從觀察者中刪除,每個主題可以有多個觀察者。
具體可觀察者ConcreteSubject: 一個具體主題實現了主題接口,除了注冊和撤銷之外,具體主題還實現了notifyObservers()方法,這個方法用來在主題狀態改變時更新所有觀察者。具體主題也可能有設置和獲取狀態的方法。
類圖:
實例:
public interface Observer
{
public void update(float temprature);
}
public class ConcreteObserver implements Observer
{
private float temperature;
private final Subject subject;
public ConcreteObserver(final Subject subject)
{
this.subject = subject;
this.subject.registerObserver(this);
}
public float getTemperature()
{
return temperature;
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
}
@Override
public void update(final float temperature)
{
this.temperature = temperature;
}
}
public interface Subject
{
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public class ConcreteSubject implements Subject
{
private final List<Observer> observers;
private float temperature;
public float getTemperature()
{
return temperature;
}
private void temperatureChanged()
{
this.notifyObservers();
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
this.temperatureChanged();
}
public ConcreteSubject()
{
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(final Observer o)
{
observers.add(o);
}
@Override
public void removeObserver(final Observer o)
{
if (observers.indexOf(o) >= 0)
{
observers.remove(o);
}
}
@Override
public void notifyObservers()
{
for (final Observer o : observers)
{
o.update(temperature);
}
}
}
public class Client
{
public static void main(final String[] args)
{
final ConcreteSubject sb = new ConcreteSubject();
sb.setTemperature((float) 20.00);
final Observer o = new ConcreteObserver(sb);
sb.setTemperature((float) 21.00);
}
}
它將觀察者和被觀察者的對象分離開。提高了應用程序的可維護性和重用性。
實現觀察者模式有很多形式,一種是“注冊---通知---撤銷注冊”的形式。
觀察者Observer:所有潛在的觀察者必須實現觀察者接口,這個接口只有update方法,當主題改變時,它被調用。
具體觀察者ConcreteObserver: 具體觀察者可以是任何實現了Observer接口的類。觀察者必須注冊具體主題,一邊接收更新。
可觀察者Subject: 主題接口,即可觀察者Observable,對象使用此接口注冊為觀察者,或者把自己從觀察者中刪除,每個主題可以有多個觀察者。
具體可觀察者ConcreteSubject: 一個具體主題實現了主題接口,除了注冊和撤銷之外,具體主題還實現了notifyObservers()方法,這個方法用來在主題狀態改變時更新所有觀察者。具體主題也可能有設置和獲取狀態的方法。
類圖:

實例:
public interface Observer
{
public void update(float temprature);
}
public class ConcreteObserver implements Observer
{
private float temperature;
private final Subject subject;
public ConcreteObserver(final Subject subject)
{
this.subject = subject;
this.subject.registerObserver(this);
}
public float getTemperature()
{
return temperature;
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
}
@Override
public void update(final float temperature)
{
this.temperature = temperature;
}
}
public interface Subject
{
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public class ConcreteSubject implements Subject
{
private final List<Observer> observers;
private float temperature;
public float getTemperature()
{
return temperature;
}
private void temperatureChanged()
{
this.notifyObservers();
}
public void setTemperature(final float temperature)
{
this.temperature = temperature;
this.temperatureChanged();
}
public ConcreteSubject()
{
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(final Observer o)
{
observers.add(o);
}
@Override
public void removeObserver(final Observer o)
{
if (observers.indexOf(o) >= 0)
{
observers.remove(o);
}
}
@Override
public void notifyObservers()
{
for (final Observer o : observers)
{
o.update(temperature);
}
}
}
public class Client
{
public static void main(final String[] args)
{
final ConcreteSubject sb = new ConcreteSubject();
sb.setTemperature((float) 20.00);
final Observer o = new ConcreteObserver(sb);
sb.setTemperature((float) 21.00);
}
}
觀察者模式的應用場景:
1、 對一個對象狀態的更新,需要其他對象同步更新,而且其他對象的數量動態可變。
2、 對象僅需要將自己的更新通知給其他對象而不需要知道其他對象的細節。
觀察者模式的優點:
1、 Subject和Observer之間是松偶合的,分別可以各自獨立改變。
2、 Subject在發送廣播通知的時候,無須指定具體的Observer,Observer可以自己決定是否要訂閱Subject的通知。
3、 遵守大部分GRASP原則和常用設計原則,高內聚、低偶合。
觀察者模式的缺陷:
1、 松偶合導致代碼關系不明顯,有時可能難以理解。(廢話)
2、 如果一個Subject被大量Observer訂閱的話,在廣播通知的時候可能會有效率問題。(畢竟只是簡單的遍歷)