觀察者模式——在對(duì)象之間定義一對(duì)多的依賴,當(dāng)一個(gè)對(duì)象改變狀態(tài),依賴它的對(duì)象都會(huì)收到通知,并自動(dòng)更新。
觀察類似于利用報(bào)紙訂閱服務(wù),只要訂閱者訂閱了該報(bào)紙,只要報(bào)紙一出版,訂閱者就會(huì)收到報(bào)紙。
只不過(guò)名稱不一樣,出版者改稱為主題(subject),訂閱者改稱為觀察者(observer)。
觀察者模式很適合下面這些場(chǎng)景中的任何一個(gè):
當(dāng)你的架構(gòu)有兩個(gè)實(shí)體類,一個(gè)依賴另一個(gè),你想讓它們互不影響或者是獨(dú)立復(fù)用它們時(shí)。
當(dāng)一個(gè)變化的對(duì)象通知那些與它自身變化相關(guān)聯(lián)的未知數(shù)量的對(duì)象時(shí)。
當(dāng)一個(gè)變化的對(duì)象通知那些無(wú)需推斷具體類型的對(duì)象時(shí)。
以下是代碼示例
package observe_v3;
/**
* 這是主題接口,對(duì)象使用此接口注冊(cè)成為觀察者,或是刪除
* 還有一個(gè)通知觀察者的功能
* */
public interface Subject {
public void addWatcher(Watcher w);
public void deleteWatcher(Watcher w);
public void notifyWatcher();
}
package observe_v3;
/**
* 觀察者接口,所有的觀察者都要實(shí)現(xiàn)該接口
* */
public interface Watcher {
public void update(Object o);
}
package observe_v3;
import java.util.ArrayList;
import java.util.List;
/**
*具體的可觀察者
* */
public class ConcreteSubject implements Subject {
private List<Watcher> watchers = new ArrayList<>();
private String str;
@Override
public void addWatcher(Watcher w) {
watchers.add(w);
}
@Override
public void deleteWatcher(Watcher w) {
watchers.remove(w);
}
@Override
public void notifyWatcher() {
for(Watcher w : watchers){
w.update(str);
}
}
public String getStr(){
return str;
}
public void setStr(String str){
this.str = str;
}
}
package observe_v3;
public class ConcreteWatcher implements Watcher {
private String name;
private Subject sub;
/* public ConcreteWatcher(String str){
this.name = str;
}*/
// 這是在構(gòu)造函數(shù)的時(shí)候就添加觀察者了
public ConcreteWatcher(Subject s, String name) {
sub = s;
this.name = name;
s.addWatcher(this);//別忘了在這邊添加注冊(cè)觀察者
}
@Override
public void update(Object o) {
System.out.println(name + ";;" + o);
}
}
package observe_v3;
public class Program {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteWatcher cw1 = new ConcreteWatcher(subject, "A");
ConcreteWatcher cw2 = new ConcreteWatcher(subject, "B");
ConcreteWatcher cw3 = new ConcreteWatcher(subject, "C");
subject.setStr("Ready");
subject.notifyWatcher();
}
}
輸出結(jié)果:
A;;Ready
B;;Ready
C;;Ready