似乎所有的設計模式都是為了使得程序具有低耦合,靈活性高,可擴展性好,程序結構清晰等等。今天的這個設計模式—觀察者模式自然也不例外,但程序結構清晰可能就不是重點了。好吧,廢話少說,模式這種簡單粗暴的東西還是要快點學習,下面直接進入正題。
定義:觀察者模式是讓對象與對象之前建立一種一對多(不是Bean之前的一對多)的關系,這種關系使得當一的一方的狀態改變時,所有多的一方自動根據一的一方的改變做出相應的改變。
使用場景:
1.
事件多級觸發。如一個公司,CEO是最頂層的被觀察者(一的一方),觀察CEO的有多個經理,如:多個總經理(多的一方)同時觀察CEO,而每個總經理有可以被多個其他經理觀察,如:項目經理,產品經理等,那么這里的總經理即是觀察者也是二級被觀察者,那么只要CEO發話,相關的總經理就要做出改變,而總經理可能又要讓底下的項目經理和業務經理做出改變,這就是事件多級觸發;
1.
關聯綁定行為,關聯行為可以拆分,即解除綁定,不是“組合”,即兩個行為是相互獨立的,不是一個整體;
1.
跨系統消息交換場景,如消息隊列,事件總線處理機制。
優點:
1.
增強程序的靈活性,可擴展性;
1.
降低程序耦合性。
缺點:
- 由于這種模式實際上是通過被觀察者用一個集合存放所有的觀察者的引用,然后依次遍歷集合調用每個觀察者的*update*方法。所以,這就產生了開發效率和運行效率的問題。還有,通常遍歷是順序的,那么所有的觀察者實際上不是同時做出更新的。更有甚者,如果其中一個觀察者更新出現卡頓,那么后面的觀察者就要延遲做出更新了,在這種情況下,通常采用多線程異步方式,然而,帶來了新的問題-并發。
下面先通過JDK自帶的*Observer*類和*Observable*實現觀察者模式
代碼實現(利用JDK內置對象):
被觀察者:
~~~
import java.util.Observable;
/**
* 被觀察者
* @author lt
*
*/
public class BeObservered extends Observable{
/**
* 提交改變,調用Observable的setChanged()和notifyObservers();
* 注意:必須調用setChanged(),然后notifyObservers()才有效
*/
public void postChanged(Object news){
// 標識被被觀察者有新的改變
setChanged();
// 通知所有的觀察者
notifyObservers(news);
}
}
~~~
?注意:
- postChanged()是我們自己寫的方法;
- 必須在這個方法里面同時調用*setChanged()*和*notifyObservers()*觀察者才會接受到變化,即回調*update*方法。
觀察者:
~~~
import java.util.Observable;
import java.util.Observer;
/**
* 觀察者
* @author lt
*
*/
public class MyObserver implements Observer{
private String name;
public MyObserver(String name){
this.name = name;
}
/**
* @param observable 該觀察者觀察的被觀察者 即BeObservered
* @param BeObservered調用notifyObservers(Object arg)時傳入的arg參數
*/
@Override
public void update(Observable observable, Object news) {
System.out.println(name+"接受到變化"+",更新的內容為:"+news);
}
@Override
public String toString() {
return "MyObserverName=" + name + "]";
}
}
~~~
?這里在*update*方法里面做了點簡單的反饋。
測試:
~~~
public class Test {
public static void main(String[] args) {
MyObserver observer1 = new MyObserver("小明");
MyObserver observer2 = new MyObserver("小麗");
MyObserver observer3 = new MyObserver("小強");
BeObservered beObervered = new BeObservered();
// 添加到觀察者隊列
beObervered.addObserver(observer1);
beObervered.addObserver(observer2);
beObervered.addObserver(observer3);
// 提交改變
beObervered.postChanged("2016,新年快樂!");
}
}
~~~
?今天是新年2016的第一天,祝福大家新年快樂,心想事成,萬事如意!
結果:

結果不用說,大家都給點反饋了(哈哈,文章點個贊,評論一番也是挺爽的)。
上面使用了JDK內置對象來實現觀察者模式,其實我們也可以自己來實現觀察者模式。下面我們自己來實現觀察者模式吧。
自定義實現觀察者模式:
被觀察者:
~~~
import java.util.HashSet;
import java.util.Set;
/**
*自定義被觀察者
* @author lt
*
*/
public class Observable {
public Set<Observer> observers = new HashSet<Observer>();
public boolean isChanged; // 默認為false
public void addObserver(Observer o){
// 防止多線程
synchronized (observers) {
observers.add(o);
}
}
public void setChanged(){
this.isChanged = true;
}
public void notifyObservers(Object arg){
if(isChanged){
// 遍歷集合,依次通知所有的觀察者
for(Observer observer : observers){
observer.update(this, arg);
}
isChanged = false; // 重置
}
}
public void notifyObservers(){
notifyObservers(null);
}
}
~~~
觀察者:
~~~
public interface Observer {
public void update(Observable observable, Object news);
}
~~~
OK,自定義實現觀察者模式完成了,將上面的MyObserver和BeObservered導入的JDK的Observer及Observable改成我們自己寫的,運行Test測試。
結果:
和用JDK的Observer及Observable是一樣的,再次祝大家新年快樂,心想事成,萬事如意!。
OK,到這里我們自己定義實現觀察者模式就完成了,是不是感覺好簡單,就是一個回調。其實,這里也并不簡單,里面肯定涉及到好多東西,什么優化啊,安全啊什么的。我們上面自己寫的類就做了一個同步處理,其他的都沒做,大家也可以去看看JDK源碼,看看它是怎么做的。
總結:
觀察者模式主要的作用是用于對象解耦,基于抽象接口(易擴展)Observer和Observable,將觀察者和被觀察者完全分離(低耦合),實現當被觀察者發生改變時相應的所有的觀察者選擇做出改變。這點有很多的用途,如我們Android開發一個軟件下載市場等需要不同的Activity可以同時需要看到同一個軟件下載的進度,還有ListView中也用到了這種模式等等。同時,知道了這種模式的原理后,我們自己也可以定義我們的觀察者和被觀察者。