詳解JAVA面向對象的設計模式 (六)、觀察者模式

觀察者模式

本篇文章大部分摘錄自 http://c.biancheng.net/view/1390.htmlhtml

在現實世界中,許多對象並非獨立存在的,其中一個對象的行爲發生改變可能會致使一個或者多個其餘對象的行爲也發生改變。例如,某種商品的物價上漲時會致使部分商家高興,而消費者傷心;還有,當咱們開車到交叉路口時,遇到紅燈會停,遇到綠燈會行。這樣的例子還有不少,例如,股票價格與股民、微信公衆號與微信用戶、氣象局的天氣預報與聽衆、小偷與警察等。java

在軟件世界也是這樣,例如,Excel 中的數據與折線圖、餅狀圖、柱狀圖之間的關係;MVC 模式中的模型與視圖的關係;事件模型中的事件源與事件處理者。全部這些,若是用觀察者模式來實現就很是方便。微信

模式的定義與特色

觀察者(Observer)模式的定義:指多個對象間存在一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。這種模式有時又稱做發佈-訂閱模式、模型-視圖模式,它是對象行爲型模式。ide

觀察者模式是一種對象行爲型模式,其主要優勢以下。測試

  1. 下降了目標與觀察者之間的耦合關係,二者之間是抽象耦合關係
  2. 目標與觀察者之間創建了一套觸發機制。

它的主要缺點以下。.net

  1. 目標與觀察者之間的依賴關係並無徹底解除,並且有可能出現循環引用
  2. 當觀察者對象不少時,通知的發佈會花費不少時間,影響程序的效率。

模式的結構與實現

實現觀察者模式時要注意具體目標對象和具體觀察者對象之間不能直接調用,不然將使二者之間緊密耦合起來,這違反了面向對象的設計原則。設計

1. 模式的結構

觀察者模式的主要角色以下。code

  1. 抽象主題(Subject)角色:也叫抽象目標類,它提供了一個用於保存觀察者對象的彙集類和增長、刪除觀察者對象的方法,以及通知全部觀察者的抽象方法。
  2. 具體主題(Concrete Subject)角色:也叫具體目標類,它實現抽象目標中的通知方法,當具體主題的內部狀態發生改變時,通知全部註冊過的觀察者對象。
  3. 抽象觀察者(Observer)角色:它是一個抽象類或接口,它包含了一個更新本身的抽象方法,當接到具體主題的更改通知時被調用。
  4. 具體觀察者(Concrete Observer)角色:實現抽象觀察者中定義的抽象方法,以便在獲得目標的更改通知時更新自身的狀態。

觀察者模式的結構圖如圖 1 所示。server

觀察者模式的結構圖

2. 實現例子

天氣做爲該例子的主題,氣象局、媽媽還有學生都是天氣的觀察者,天氣發出提醒時,全部天氣觀察者都會作出迴應。htm

// 抽象主題
public abstract class AbstractSubject {
    protected List<Observer> observerList = new ArrayList<>();

    public void add(Observer observer) {
        observerList.add(observer);
    }

    public void remove(Observer observer) {
        observerList.remove(observer);
    }

    public abstract void notifyObservers(String status);
}

// 抽象觀察者
public interface Observer {
    void response(String status);
}

// 具體主題
public class WeatherSubject extends AbstractSubject {
    @Override
    public void notifyObservers(String status) {
        for (Observer ob : observerList) {
            ob.response(status);
        }
    }
}

// 具體觀察者 (氣象局、媽媽、學生)
public class WeatherCenterObserver implements Observer {
    @Override
    public void response(String status) {
        if ("rain".equals(status))
            System.out.println("氣象局:要下雨了!");
        else
            System.out.println("氣象局:天氣晴朗!");
    }
}

// 媽媽
public class MomObserver implements Observer {
    @Override
    public void response(String status) {
        if ("rain".equals(status)) 
            System.out.println("媽媽:下雨了!回家收衣服!");
        else
            System.out.println("媽媽:好天氣,曬衣服!");
    }
}

// 學生
public class StudentObserver implements Observer {
    @Override
    public void response(String status) {
        if ("rain".equals(status))
            System.out.println("學生黨:下雨了,出門帶傘!");
        else
            System.out.println("學生黨:天氣好!不用帶傘出門!");
    }
}

測試例子

public static void main(String[] args) {
        AbstractSubject weatherSubject = new WeatherSubject();
        weatherSubject.add(new WeatherCenterObserver());
        weatherSubject.add(new MomObserver());
        weatherSubject.add(new StudentObserver());
        weatherSubject.notifyObservers("rain");
    }

// 輸出結果:
// 氣象局:要下雨了!
// 媽媽:下雨了!回家收衣服!
// 學生黨:下雨了,出門帶傘!

我只作了一個簡單的例子便於理解觀察者模式,實際使用中,每每經過JMS和MQ來輔助實現觀察者模式,而且須要事件相關對象的傳導(使用泛型),這都是更高級的設計裏須要考慮到的。

模式的應用場景

經過前面的分析與應用實例可知觀察者模式適合如下幾種情形。

  1. 對象間存在一對多關係,一個對象的狀態發生改變會影響其餘對象。
  2. 當一個抽象模型有兩個方面,其中一個方面依賴於另外一方面時,可將這兩者封裝在獨立的對象中以使它們能夠各自獨立地改變和複用。

模式的擴展

Java 中,經過 java.util.Observable 類和 java.util.Observer 接口定義了觀察者模式,只要實現它們的子類就能夠編寫觀察者模式實例。

1. Observable類

Observable 類是抽象目標類,它有一個 Vector 向量,用於保存全部要通知的觀察者對象,下面來介紹它最重要的 3 個方法。

  1. void addObserver(Observer o) 方法:用於將新的觀察者對象添加到向量中。
  2. void notifyObservers(Object arg) 方法:調用向量中的全部觀察者對象的 update。方法,通知它們數據發生改變。一般越晚加入向量的觀察者越先獲得通知。
  3. void setChange() 方法:用來設置一個 boolean 類型的內部標誌位,註明目標對象發生了變化。當它爲真時,notifyObservers() 纔會通知觀察者。

2. Observer 接口

Observer 接口是抽象觀察者,它監視目標對象的變化,當目標對象發生變化時,觀察者獲得通知,並調用 void update(Observable o,Object arg) 方法,進行相應的工做。

原油期貨的觀察者模式實例的結構圖

3. 實現

http://c.biancheng.net/view/1390.html

相關文章
相關標籤/搜索