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

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


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


觀察者模式

簡述:被觀察者發生變化時,全部被觀察者都會通知。java

需求:要求報紙發佈的時候,讀者能夠及時收到報紙的最新報道。git

根據以前屢次的反例經驗,要作好面向接口和抽象編程的設計。github

此次直接上,算法

正例 #1:

爲觀察者定義一個接口。編程

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

     void disObservered(TheSubject subject);

     void doObservered(TheSubject subject);
}

這裏有一個問題:爲何不用抽象類進行抽象?設計模式

由於不知道觀察者模式的應用都是怎麼樣的。現實編程中,具體的觀察者徹底有多是風馬牛不相及的類,但它們都須要根據通知者的通知來作出update()的操做,因此讓它們都實現Observer接口,並重寫相關方法便可。app

定義一個觀察者:ide

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);
}

唉?那這裏爲何不能夠用接口呢?post

注意到有一個變量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相互依賴,並不涉及相關具體的觀察者和被觀察者,符合依賴倒置原則

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

最後總結觀察者模式:

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

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

相關文章
相關標籤/搜索