觀察者模式書面表述是:觀察者模式定義了對象間的一種一對多依賴關系,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新,它將觀察者和被觀察者的對象分離開。提高了應用程序的可維護性和重用性。
在設計一組依賴的對象與它們所依賴的對象之間一致(同步)的交互模型時,觀察者模式(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 List5.測試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(); } } } } }
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,有大量的現金和黃金,特警提高警惕,貼身保護