- 定義
- 類型
- 類圖
- 結構
- 有趣的例子
定義:定義對象間一種一對多的依賴關係,使得當每一個對象改變狀態,則所有依賴於它的對象都會得到通知並自動更新。
類型:行爲類模式
類圖:
結構:在最基礎的觀察者模式中,包括以下四個角色:
- 被觀察者:從類圖中可以看到,類中有一個用來存放觀察者對象的Vector容器(之所以使用Vector而不使用List,是因爲多線程操作時,Vector在是安全的,而List則是不安全的),這個Vector容器是被觀察者類的核心,另外還有三個方法:attach方法是向這個容器中添加觀察者對象;detach方法是從容器中移除觀察者對象;notify方法是依次調用觀察者對象的對應方法。這個角色可以是接口,也可以是抽象類或者具體的類,因爲很多情況下會與其他的模式混用,所以使用抽象類的情況比較多。
- 觀察者:觀察者角色一般是一個接口,它只有一個update方法,在被觀察者狀態發生變化時,這個方法就會被觸發調用。
- 具體的被觀察者:使用這個角色是爲了便於擴展,可以在此角色中定義具體的業務邏輯。
- 具體的觀察者:觀察者接口的具體實現,在這個角色中,將定義被觀察者對象狀態發生變化時所要處理的邏輯。
有趣的例子
1.假設我們有一情景是這樣子的:小孩子在睡覺,醒來後爸爸要給孩子喂東西吃,爺爺要抱小孩子,叔叔要親小孩子。
從情景中我們分析:首先孩子當前的狀態是睡着的,爸爸,爺爺,叔叔都需要觀察小孩子睡醒後才能進行一系列動作。那麼我們很容易想到的就是在實現的時候將小孩子的類封裝到爸爸,爺爺,和叔叔的類中,讓爸爸,爺爺,叔叔去主動觀察小孩子的狀態。這是一種可行的方法,但是此方法需要不斷的去監視小孩子的狀態,導致爸爸,爺爺,叔叔在小孩子睡着的這段時間一直處於狀態,這樣是不是太累了。因此我們想到:將這些觀察者的類封裝到小孩子的類中,讓小孩子主動醒來去通知觀察者來執行相應的操作,這就是我們所要說的觀察者模式。
那麼接下來我們來實現這一情景需求:
Test.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
class WakenUpEvent {
private long time;
private String location;
private Child source;
public WakenUpEvent(long time, String location, Child source) {
super();
this.time = time;
this.location = location;
this.source = source;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Child getSource() {
return source;
}
public void setSource(Child source) {
this.source = source;
}
}
class Child implements Runnable {
private java.util.List<WakenUpListener> wakenUplisteners = new ArrayList<WakenUpListener>();
public void addWakenUpListener(WakenUpListener l) {
wakenUplisteners.add(l);
}
public void wakeUp() {
for (int i = 0; i < wakenUplisteners.size(); i++) {
WakenUpListener l = wakenUplisteners.get(i);
l.ActionToWakenUp(new WakenUpEvent(System.currentTimeMillis(),
"bed", this));
}
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.wakeUp();
}
}
class Dad implements WakenUpListener {
public void ActionToWakenUp(WakenUpEvent wakenUpEvent) {
System.out.println("feed child");
}
}
class GrandFather implements WakenUpListener {
public void ActionToWakenUp(WakenUpEvent wakenUpEvent) {
System.out.println("hug child");
}
}
interface WakenUpListener {
public void ActionToWakenUp(WakenUpEvent wakenUpEvent);
}
class PropertyMgr {
private static Properties properties = new Properties();
static {
try {
properties.load(Test.class.getClassLoader().getResourceAsStream(
"zhaowanyue/observer.properties"));
} catch (IOException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
}
public static String getProperty(String key) {
return properties.getProperty(key);
}
}
public class Test {
public static void main(String[] args) throws IOException {
Child child = new Child();
String[] observers = PropertyMgr.getProperty("observers").split(",");
for (String s : observers) {
try {
child.addWakenUpListener((WakenUpListener) Class.forName(s)
.newInstance());
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
e.printStackTrace();
}
}
new Thread(child).start();
}
}
observer.properties
observers=zhaowanyue.Dad,zhaowanyue.GrandFather