觀察者模式定義:
定義一個對象間的一對多的依賴關係。當一個對象的狀態發生改變,所有依賴於它的對象都得到通知並被自動更新。
Subject :目標對象
一個目標對象有多個觀察者觀察
提供觀察者的添加和刪除維護
目標發生變化時通知所有的觀察者
Observer:觀察者的介面,提供目標式通知時對應的更新方法
ConcreteSubject:具體的目標對象
ConcreteObserver:具體的觀察者對象
Subject類:
package com.light.com;import java.util.ArrayList;import java.util.List;public class Subject {private List<Observer> observers = new ArrayList<Observer>();public void attach(Observer o) {observers.add(o);}public void detach(Observer o) {observers.remove(o);}protected void notifyObservers() {for (Observer o : observers) {o.update(this);}}}
Observer介面:
package com.light.com;public interface Observer {//更新訊息 public void update(Subject subject);}
ConcreteSubject類:
package com.light.com;public class ConcreteSubject extends Subject {//有新訊息private String news;public String getNews() {return news;}public void setNews(String news) {this.news = news;System.out.println("探子回來了,有重要訊息");this.notifyObservers();}}
ConcreteObserver類:
package com.light.com;public class ConcreteObserver implements Observer { private String name; public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void update(Subject subject) {//列印新訊息 System.out.println(name+"收到了訊息,內容是:"+((ConcreteSubject)subject).getNews());}}
用戶端:
package com.light.com;public class Client {/** * @param args */public static void main(String[] args) { ConcreteSubject paper = new ConcreteSubject(); ConcreteObserver reader1 = new ConcreteObserver(); reader1.setName("孫權"); ConcreteObserver reader2 = new ConcreteObserver(); reader2.setName("劉備"); ConcreteObserver reader3 = new ConcreteObserver(); reader3.setName("織田信長"); paper.attach(reader1); paper.attach(reader2); paper.attach(reader3); paper.setNews("曹操到了"); System.out.println("--------------"); paper.setNews("曹操回去了");}}
運行結果:
探子回來了,有重要訊息
孫權收到了訊息,內容是:曹操到了
劉備收到了訊息,內容是:曹操到了
織田信長收到了訊息,內容是:曹操到了
--------------
探子回來了,有重要訊息
孫權收到了訊息,內容是:曹操回去了
劉備收到了訊息,內容是:曹操回去了
織田信長收到了訊息,內容是:曹操回去了
分析一下流程:假設一個探子持有三方統帥的軍令,一旦有新訊息立即更新自己的資訊庫並通知所有統帥我的資訊庫有更新快來看看,統帥都有探子的引用便於觀察。一旦資訊庫更新,統帥可以根據這個引用看到探子更新的最新資訊。主帥依賴於探子得到情報,但探子不依賴於主帥,比如探子覺得某個統帥的工資給低了,不願幫他做事,就把這個統帥從中去除,去除的統帥也就無法得到資訊了。主帥總是被動的等到探子回報資訊。
通常我們在JAVA中實現觀察者模式,只需要繼承系統提供的2個類Observable類和Observer類,其他工作系統已經幫我們封裝好了
ConcreteSubject類
package com.light.com;public class LingLingQi extends java.util.Observable {private String news;public String getNews() {return news;}public void setNews(String news) {this.news = news;//有新訊息了更新訊息庫this.setChanged();//通知統帥吧 這裡可以選擇只通知這個新訊息,而不給統帥自己的引用,可能有其他的訊息很寶貴不能給統帥自己留著this.notifyObservers(news);//把自己所有的資訊暴露給統帥,毫無保留//this.notifyObservers();}}
ConcreteObserver類
package com.light.com;import java.util.Observable;public class General implements java.util.Observer { private String name; public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {System.out.println(name+"收到了訊息:"+arg);}}
Client用戶端
package com.light.com;public class Client {/** * @param args */public static void main(String[] args) { LingLingQi l = new LingLingQi(); General wuTian = new General(); wuTian.setName("武田信玄"); General shangShan = new General(); shangShan.setName("上杉謙信"); General yiDa = new General(); yiDa.setName("伊達政宗"); l.addObserver(wuTian); l.addObserver(shangShan); l.addObserver(yiDa); l.setNews("信長掛了"); System.out.println("------幾天后"); l.setNews("羽柴秀吉來了");}}
運行結果:
伊達政宗收到了訊息:信長掛了
上杉謙信收到了訊息:信長掛了
武田信玄收到了訊息:信長掛了
------幾天后
伊達政宗收到了訊息:羽柴秀吉來了
上杉謙信收到了訊息:羽柴秀吉來了
武田信玄收到了訊息:羽柴秀吉來了
android中的各種事件監聽就用到了觀察者模式,只是一個觀察者觀察了多個目標對象,就好比統帥派出了多個探子,每個探子都通過不同的介面通知統帥資訊發生了變化。