設計模式 #6 (觀察者模式)


設計模式 #6 (觀察者模式)


文章中所有工程代碼和UML建模文件都在我的這個GitHub的公開庫--->DesignPatternStar來一個好嗎?秋梨膏!


觀察者模式

簡述:被觀察者發生變化時,所有被觀察者都會通知。

需求:要求報紙發布的時候,讀者可以及時收到報紙的最新報道。

根據之前多次的反例經驗,要做好面向接口和抽象編程的設計。

這次直接上,

正例 #1:

為觀察者定義一個接口。

//觀察者接口
 interface  Observer {
     void update(String Data);

     void disObservered(TheSubject subject);

     void doObservered(TheSubject subject);
}

這里有一個問題:為什么不用抽象類進行抽象?

因為不知道觀察者模式的應用都是怎么樣的。現實編程中,具體的觀察者完全有可能是風馬牛不相及的類,但它們都需要根據通知者的通知來做出update()的操作,所以讓它們都實現Observer接口,並重寫相關方法即可。

定義一個觀察者:

public class Reader implements Observer{
    private String name ;

    public Reader(String name) {
        this.name = name;
    }

    @Override
    public void update(String Data) {
        System.out.println(this.name+"收到報紙,閱讀最新報道:"+Data);
    }

    @Override
    public void disObservered(TheSubject subject) {
        subject.removeObserver(this);
    }

    @Override
    public void doObservered(TheSubject subject) {
        subject.addObserver(this);
    }
}
//被觀察者抽象類
public abstract class TheSubject {
    //觀察者列表
    protected List<Observer> observerList = new ArrayList<>();
    //加入到觀察者列表
    public  boolean addObserver(Observer observer){
        return  observerList.add(observer);
    }
    //從觀察者列表移除
    public  boolean removeObserver(Observer observer){
        return observerList.remove(observer);
    }
    //變化,並通知觀察者
    public abstract void setChange(String Data);
    //為觀察者更新內容
    public abstract void upDataObserver(String Data);
}

唉?那這里為什么不可以用接口呢?

注意到有一個變量observerList了嗎?

我們先假設TheSubject抽象類是一個接口,如果是需要一個類成為被觀察者,那么就會讓他實現這一接口,也是需要定義它的觀察者列表observerList,如果是每一個被觀察者都需要重新定義自己的觀察者列表observerList,還要在實現addObserverremoveObserver兩個方法,這兩個方法都是固定的算法。重復太多的代碼就會有壞的味道的。

這時候,將重復的代碼寫在抽象類TheSubject,被觀察者進行繼承即可。

public class News_pappers extends TheSubject{
    private  String news;

    public String getNews() {
        return news;
    }

    @Override
    public void setChange(String Data) {
        this.news ="最新報道:"+ Data;
        System.out.println("發布最新報道:"+Data);
        upDataObserver(Date);
    }

    @Override
    public void upDataObserver(String Data) {
        for (Observer observer : observerList) {
            observer.update(Data);
        }
    }
}
public class postive {
/*================客戶端============================*/
    public static void main(String[] args) {
        News_pappers newspaper = new News_pappers();
        Reader lili = new Reader("lili");
        Reader mumu = new Reader("mumu");
        Reader shanshan = new Reader("shanshan");

        newspaper.addObserver(lili);
        newspaper.addObserver(mumu);
        newspaper.addObserver(shanshan);

        newspaper.setChange("Big News");

        shanshan.disObservered(newspaper);

        newspaper.setChange("small00000 News");

        News_pappers news_pappers_02 = new News_pappers();
        mumu.doObservered(news_pappers_02);
        news_pappers_02.setChange("大新聞");

    }
}

運行結果:

image-20200921201557214

UML類圖:

image-20200921204803554

細心的讀者可能已經發現,這里遵守的設計原則有:

  • 增加其他類型觀察者時,只需要Observer接口即可;增加被觀察者繼承抽象類TheSubject即可,符合開閉原則
  • 接口Observer和抽象類TheSubject相互依賴,並不涉及相關具體的觀察者和被觀察者,符合依賴倒置原則

其實接觸過安卓都知道,安卓的內容提供者和內容觀察者,廣播機制都有點觀察者模式的味道。

最后總結觀察者模式:

  • 當一個對象的改變需要同時改變其他對象的時候,而且它不知道具體有多少對象有待改變時,應該考慮使用觀察者模式。
  • 當一個抽象模型有兩個方面,其中一方面依賴於另一方面,這時用觀察者模式可以將這兩者封裝在獨立的對象中使它們各自獨立地改變和復用
  • 觀察者模式所做的工作其實就是在解除耦合。讓耦合的雙方都依賴於抽象,而不是依賴於具體。從而使得各自的變化都不會影響另一邊的變化。
  • 觀察者和被觀察者可以是多對多的關系。
  • 觀察者抽象成接口,被觀察者抽象於抽象類比較合適。

這是最后一篇關於設計模式的相關隨筆,回顧以往設計模式相關原創隨筆請點擊---> 設計原則和常用設計模式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM