定義:
定義對象間一種一對多的依賴關(guān)系滥壕,使得當每一個對象改變狀態(tài)陵且,則所有依賴于它的對象都會得到通知并自動更新。
類型:
行為類模式
類圖:
使用場景 :
在軟件系統(tǒng)中經(jīng)常會有這樣的需求:如果一個對象的狀態(tài)發(fā)生改變,某些與它相關(guān)的對象也要隨之做出相應(yīng)的變化。比如璃氢,我們要設(shè)計一個右鍵菜單的功能,只要在軟件的有效區(qū)域內(nèi)點擊鼠標右鍵录择,就會彈出一個菜單拔莱;再比如,我們要設(shè)計一個自動部署的功能隘竭,就像eclipse開發(fā)時,只要修改了文件讼渊,eclipse就會自動將修改的文件部署到服務(wù)器中动看。這兩個功能有一個相似的地方,那就是一個對象要時刻監(jiān)聽著另一個對象爪幻,只要它的狀態(tài)一發(fā)生改變菱皆,自己隨之要做出相應(yīng)的行動。其實挨稿,能夠?qū)崿F(xiàn)這一點的方案很多仇轻,但是,無疑使用觀察者模式是一個主流的選擇奶甘。
觀察者模式的結(jié)構(gòu)
在最基礎(chǔ)的觀察者模式中篷店,包括以下四個角色:
被觀察者:從類圖中可以看到,類中有一個用來存放觀察者對象的Vector容器(之所以使用Vector而不使用List,是因為多線程操作時疲陕,Vector在是安全的方淤,而List則是不安全的),這個Vector容器是被觀察者類的核心蹄殃,另外還有三個方法:attach方法是向這個容器中添加觀察者對象携茂;detach方法是從容器中移除觀察者對象;notify方法是依次調(diào)用觀察者對象的對應(yīng)方法诅岩。這個角色可以是接口讳苦,也可以是抽象類或者具體的類,因為很多情況下會與其他的模式混用吩谦,所以使用抽象類的情況比較多鸳谜。
觀察者:觀察者角色一般是一個接口,它只有一個update方法逮京,在被觀察者狀態(tài)發(fā)生變化時卿堂,這個方法就會被觸發(fā)調(diào)用。
具體的被觀察者:使用這個角色是為了便于擴展懒棉,可以在此角色中定義具體的業(yè)務(wù)邏輯草描。
具體的觀察者:觀察者接口的具體實現(xiàn),在這個角色中策严,將定義被觀察者對象狀態(tài)發(fā)生變化時所要處理的邏輯穗慕。
代碼實現(xiàn) :
被觀察者 :
public class Teacher {
/**
* 模擬發(fā)布消息
*/
public void publishMessage(String message) {
//通知所有的觀察者
notifyObservers(message);
}
//1.定義接口和接口方法
public interface MessageObserver {
void onMessageChanged(String message);
}
//2.定義接口對象的集合
private List<MessageObserver> observers = new ArrayList<>();
//3.添加觀察者
public synchronized void addObserver(MessageObserver o) {
if (o == null)
throw new NullPointerException();
if (!observers.contains(o)) {
observers.add(o);
}
}
//4.移除觀察者
public synchronized void deleteObserver(MessageObserver o) {
observers.remove(o);
}
//5.通知所有的觀察者
public void notifyObservers(String message) {
for (MessageObserver o : observers) {
o.onMessageChanged(message);
}
}
}
觀察者 :
public class Student1 implements MessageObserver {
@Override
public void onMessageChanged(String message) {
System.out.println(this.getClass().getSimpleName() + " 接收到消息 : " + message);
}
}
測試類 :
public class Test {
public static void main(String[] args) {
//1.創(chuàng)建發(fā)布消息的人
Teacher t = new Teacher();
//2.創(chuàng)建接收消息的人
Student1 student1 = new Student1();
Student2 student2 = new Student2();
Student3 student3 = new Student3();
Student4 student4 = new Student4();
//訂閱消息
t.addObserver(student1);
t.addObserver(student2);
t.addObserver(student3);
t.addObserver(student4);
//模擬發(fā)布消息
t.publishMessage("考試成績不合格的中秋節(jié)不能放假");
}
}
參考資料:
http://wiki.jikexueyuan.com/project/java-design-pattern/observer-pattern.html