觀察者模式書面表述是:觀察者模式定義了對象間的一種一對多依賴關系,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新,它將觀察者和被觀察者的對象分離開。提高了應用程序的可維護性和重用性。
在設計一組依賴的對象與它們所依賴的對象之間一致(同步)的交互模型時,觀察者模式(Observer Pattern)很有用。它可以使依賴對象的狀態與它們所依賴的對象的狀態保持同步。這組依賴的對象指的是觀察者(Observer),它們所依賴的對象稱為主題(Subject)。為了實現觀察者(Observer)與主題(Subject)的狀態保持同步,應使用觀察者模式。觀察者(Observer)模式是對象的行為型模式,又叫做發表-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-收聽者(Source/Listener)模式或從屬者(Dependents)模式。推薦采用發布者--訂閱者(publisher--subscriber)模型,以使這組觀察者和主題對象之間有清晰的界限,對應關系為: publisher--subscriber -->> Subject--Observer。
常見的實例有:訂閱模式(RSS),數據更新操作update(),Android端常用的廣播模式
在觀察者模式裡有如下的角色:
抽象主題(Subject)角色:
主題角色是將觀察者的對象的引用保存在一個集合或者列表中;每個主題都可以有任何數量的觀察者。主題提供一個接口可以添加觀察者和刪除觀察者的操作;主題角色又叫做抽象被觀察者(Observable)角色;
抽象主題角色,有時又叫做抽象被觀察者角色(Observable),采用接口或者抽象類來實現。
抽象觀察者(Observer)角色:
這個角色就是用來實現數據更新行為的,是為觀察者提供接口的行為,得到操作的請求後更新自己。
抽象觀察者角色,可以用一個抽象類或者一個接口實現;在具體的情況下也不排除使用具體類實現。
具體主題(ConcreteSubject)角色:
保存對具體觀察者對象有用的內部狀態;在這種內部狀態改變時給其觀察者發出一個通知;具體主題角色又叫作具體被觀察者角色;
具體主題角色,通常用一個具體子類實現。
具體觀察者(ConcreteObserver)角色:
保存一個指向具體主題對象的引用;和一個與主題的狀態相符的狀態。具體觀察者角色實現抽象觀察者角色所要求的更新自己的接口,以便使本身的狀態與主題的狀態自恰。
1)Subject 需要為注冊和注銷觀察者分別提供一個接口(如add, remover接口)。
2)Observer(觀察者)需要提供一個可以從Subject接受通知的接口(如update,operate接口)。
Subject在狀態發生變化時,利用改接口通知相應的Observer。
3)下面的兩點也需要滿足:
(1)拉模型(In the pull model)--主題需要提供一個接口,可以使觀察者查詢主題獲得需要的狀態信息來更新自己的狀態。
(2)推模型(In the push model)--主題發送觀察者可能關注的狀態信息。
public interface OberverMethod {
void updata();
}
public class ObjectOne implements OberverMethod{
public void updata() {
System.out.println("車號:閩AAA888,有大量的現金和黃金,保安提高警惕,貼身保護");
}
}
2)盜賊角色
public class ObjectTwo implements OberverMethod{
public void updata() {
System.out.println("車號:閩AAA888,有大量的現金和黃金,注意隨時准備炸彈,大干一票");
}
}
3)盜賊角色
public class ObjectThress implements OberverMethod{
public void updata() {
System.out.println("車號:閩AAA888,有大量的現金和黃金,特警提高警惕,貼身保護");
}
}
public interface Watche {
void addWatcher(OberverMethod watcher);
void removeWatcher(OberverMethod watcher);
void notifyWatchers();
}
public class OperacteWatche implements Watche {
private List list = new ArrayList();
public synchronized void addWatcher(OberverMethod watcher){
if(watcher == null){
throw new NullPointerException();
}
if(!list.contains(watcher)){
list.add(watcher);
}
}
public void removeWatcher(OberverMethod watcher) {
list.remove(watcher);
}
public void notifyWatchers() {
if(list != null && list.size() > 0){
for(OberverMethod entity : list ){
if(entity != null){
entity.updata();
}
}
}
}
}
5.測試
Watche watche = new OperacteWatche();
OberverMethod method1 = new ObjectOne();
OberverMethod method2 = new ObjectTwo();
OberverMethod method3 = new ObjectThress();
System.out.println("全部通知");
watche.addWatcher(method1);
watche.addWatcher(method2);
watche.addWatcher(method3);
watche.notifyWatchers();
System.out.println("只通知保安和警察");
watche.removeWatcher(method2);
watche.notifyWatchers();
全部通知 車號:閩AAA888,有大量的現金和黃金,保安提高警惕,貼身保護 車號:閩AAA888,有大量的現金和黃金,注意隨時准備炸彈,大干一票 車號:閩AAA888,有大量的現金和黃金,特警提高警惕,貼身保護 只通知保安和警察 車號:閩AAA888,有大量的現金和黃金,保安提高警惕,貼身保護 車號:閩AAA888,有大量的現金和黃金,特警提高警惕,貼身保護