觀察者模式(Observer)就是定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴它的對象都得到通知并被自動更新。
對于觀察者模式的原理圖:

通過一個一個抽象的主題Subject保存了多個信息處理列表,可以添加多個觀察者,實現即時的通知觀察者最新動態然后分別派生子類對象對具體的消息和狀態做出處理,下面我們聯系到具體的問題:正好我還在讀,就拿學校通知公告來舉例子吧,學校發布一個公告,要通知學生,老師,保潔阿姨,和食堂等相應的通知,這樣才能正常的進行工作,比如這次清明放假,要通知所有機關和單位做好準備,這樣才能保證正常有序的進行,下面是簡單的原理圖和例子程序:
換了一個UML這次用的一個jude很好的簡單實用,而且這個是免安裝的
提供了一下下載地址
[http://download.csdn.net/detail/wclxyn/4226796](http://download.csdn.net/detail/wclxyn/4226796)(不需要財富值)
示例原理圖(新手原理圖不對之處請多多指教)

首先定義接口觀察者,定義接受消息的方法,具體內容如下:
~~~
package com.designpattern.observer;
public interface Observer {
public void receive(String message);
}
~~~
然后分別寫教師,學生,食堂,保潔觀察者的實現類:
~~~
package com.designpattern.observer;
public class Teachers implements Observer {
@Override
public void receive(String message) {
System.out.println("教師收到" + message);
}
}
~~~
~~~
package com.designpattern.observer;
public class Students implements Observer {
@Override
public void receive(String message) {
System.out.println("學生收到" + message);
}
}
~~~
~~~
package com.designpattern.observer;
public class Mess implements Observer {
@Override
public void receive(String message) {
System.out.println("食堂收到" + message);
}
}
~~~
~~~
package com.designpattern.observer;
public class Cleaner implements Observer {
@Override
public void receive(String message) {
System.out.println("保潔收到" + message);
}
}
~~~
然后定義被觀察者接口,具體這里是學校,定義了通知公告的方法announcement方法和提醒方法notifyReceive方法同時定義add和romove觀察者的方法,這里用synchronized控制添加和移除,為了操作的便捷,定義返回值為School,這樣能連續操作,如下:
~~~
office.addObserver(new Mess()).addObserver(new Students()).addObserver(
new Teachers()).addObserver(new Cleaner());
~~~
具體的School如下:
~~~
package com.designpattern.observer;
import java.util.ArrayList;
import java.util.List;
public abstract class School {
private List<Observer> observers = new ArrayList<Observer>();
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void announcement() {
notifyRecevie();
}
public synchronized School addObserver(Observer observer) {
observers.add(observer);
return this;
}
public synchronized School removeObserver(Observer observer) {
observers.remove(observer);
return this;
}
public void notifyRecevie() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.receive(getMessage());
}
}
}
~~~
然后具體的實例類Office進行具體的通知:
~~~
package com.designpattern.observer;
public class Office extends School {
@Override
public void announcement() {
System.out.println("政教處通知明天放假");
this.setMessage("明天放假");
super.announcement();
System.out.println("---------------------");
}
}
~~~
之后客戶端調用:
~~~
package com.designpattern.observer;
public class Client {
public static void main(String[] args) {
Office office = new Office();
office.addObserver(new Mess()).addObserver(new Students()).addObserver(
new Teachers()).addObserver(new Cleaner());
office.announcement();
}
}
~~~
然后打印結果如下,如果動態的添加和移除觀察者都能實現通知:
~~~
政教處通知明天放假
食堂收到明天放假
學生收到明天放假
教師收到明天放假
保潔收到明天放假
---------------------
~~~
在java的API里面也封裝好了這樣一個觀察者的接口
具體的實例時觀察者繼承Observer類,被觀察者實現Observable接口然后調用其中的具體方法,操作很簡單具體參見API就可以了,簡單些了一個小Demo:
~~~
package wlzx.mh.observer;
import java.util.Observable;
public class House extends Observable {
private float price;
private String name;
public String getName() {
return name;
}
public House(float price) {
this.price = price;
}
public String toString(){
return "House.java" ;
}
public float getPrice() {
return price;
}
public void setName(String name) {
this.name = name;
super.setChanged();
super.notifyObservers(name);
}
public void setPrice(float price) {
super.setChanged();// 通知內容已經可以被修改了
this.price = price;
// 一旦修改,則表示價格改變,那么價格改變之后,實際上應該立刻通知所有的觀察者
super.notifyObservers(price);// 通知所有的觀察者已經改變
}
}
~~~
~~~
package wlzx.mh.observer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Observable;
import java.util.Observer;
public class Person implements Observer {
// arg表示改變之后的內容
// o表示觀察的對象
public String getDateTime() {
return (new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS")
.format(new Date())).toString();
}
public void update(Observable o, Object arg) {
System.out.println(getDateTime() + "----" + o + "----" + arg);
}
}
~~~
~~~
package wlzx.mh.observer;
public class TestObserver {
public static void main(String[] args) {
House h = new House(3000.0f);
Person per1 = new Person();
Person per2 = new Person();
Person per3 = new Person();
h.addObserver(per1);// 增加一個觀察者
h.addObserver(per2);// 增加一個觀察者
h.addObserver(per3);// 增加一個觀察者
h.setPrice(6000.0f);// 要通知觀察者內容已經被改變了
h.setName("wclxyn");
}
}
~~~
~~~
2012-04-14 11:44:30.578----House.java----6000.0
2012-04-14 11:44:30.578----House.java----6000.0
2012-04-14 11:44:30.578----House.java----6000.0
2012-04-14 11:44:30.578----House.java----wclxyn
2012-04-14 11:44:30.578----House.java----wclxyn
2012-04-14 11:44:30.578----House.java----wclxyn
~~~
這樣具體的內容改變都會被監控了。
觀察者模式在被觀察者和觀察者之間建立一個抽象的耦合,每一個具體的觀察者都符合一個抽象觀察者的接口,被觀察者并不知道任何一個具體的觀察者,他只知道他們有一個共同的接口,從而使得被觀察者和觀察者耦合度降低,而且觀察者模式支持廣播通信。被觀察者會向所有注冊過的觀察者發出通知,但是如果一個被觀察者有N個觀察者那么在通知過程種會耗費大量的時間。
- 前言
- 前言(目錄、源碼、資料)
- (一)簡單工廠模式(SimpleFatory)
- (二)工廠方法模式(FactoryMethod)
- (三)抽象工廠模式(AbstractFactory)
- (四)創建者模式(Builder)
- (五)原型模式(Prototype)
- (六)單例模式(Singleton)
- (七)外觀模式(Facade)
- (八)適配器模式(Adapter)
- (九)代理模式(Proxy)
- (十)裝飾模式(Decorator)
- (十一)橋模式(birdge)
- (十二)組合模式(Composite)
- (十三)享元模式(Flyweight)
- (十四)模板方法模式(Template)
- (十五)觀察者模式(Observer)
- (十六)狀態模式(State)