漫畫設計模式:每週一篇設計模式之觀察者模式

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
以下圖,產品經理接到老闆通知,須要臨時新增需求,萬能的產品經理,馬上通知全部程序員去實現該需求。
在這裏插入圖片描述
小安用程序的形式實現上圖的過程,代碼以下:

/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 老闆
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class Boss {
    public void sendOrder(){
        ProductManager productManager = new ProductManager();
        productManager.demandChanged();
    }
}
複製代碼
/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 產品經理
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class ProductManager {
    public void demandChanged(){
        Programmer programmer1 = new Programmer();
        Programmer programmer2 = new Programmer();
        Programmer programmer3 = new Programmer();
        programmer1.updateCode();
        programmer2.updateCode();
        programmer3.updateCode();
    }
}
複製代碼
/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 程序員
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class Programmer {
    public void updateCode(){
        //苦逼的完成需求
    }
}
複製代碼

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
觀察者模式:

定義了對象之間的一對多依賴,這樣一來,當一個對象改變狀態時,它的全部依賴着都會受到通知並自動更新。程序員

官方定義不太好理解,我翻譯一下,在觀察者模式中,對象之間有一對多的依賴關係,好比一個產品經理對多個程序員,當產品經理有需求變動時,他的全部依賴的程序員都會收到需求變動通知,並修改本身的程序完成該需求。bash

採用觀察者模式的UML圖: ide

在這裏插入圖片描述

繼承Subject的類:就是觀察者模式中的「被觀察者」,它會把全部觀察者保存在一個集合中。 實現Observer的類:就是觀察者模式中的「觀察者」,它會把本身註冊進被觀察者中的集合中,從而使被觀察者發生改變時,通知本身;也能夠把本身從被觀察者集合中刪除,從而不接受觀察者發來的通知。學習

被觀察者父類:ui

/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 抽象者父類
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class Subject {
    //觀察者對象列表
    private List<Observer> observers = new ArrayList<Observer>();

    /**
     * 註冊觀察者對象
     * @param observer
     */
    public void registerObserver(Observer observer){
        if(!observers.contains(observer)) {
            observers.add(observer);
        }
    }

    /**
     * 解綁觀察者對象
     */
    public void unRegisterObserver(Observer observer){
        if(!observers.contains(observer)) {
            observers.remove(observer);
        }
    }

    //通知全部註冊的觀察者執行對應操做
    public  void notifyObservers(){
        for (Observer observer : observers) {
            observer.updateCode();
        }
    }
}
複製代碼

具體的被觀察者:this

/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 具體的被觀察者(產品經理)
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class ProductManager  extends Subject{

    private static class ProductManagerSingletonHolder {
        private static final ProductManager INSTANCE = new ProductManager();
    }
    private ProductManager (){}
    public static final ProductManager getInstance() {
        return ProductManagerSingletonHolder.INSTANCE;
    }

    //需求變動,通知觀察者
    public void demandChanged(){
        notifyObservers();
    }
}
複製代碼

觀察者公共接口:spa

/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 抽象的觀察者,全部的觀察者都實現該接口
 * 當被觀察者有變化須要通知時,有了一個共同的接口。
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public interface Observer {
     void updateCode();
}
複製代碼

具體觀察者對象:翻譯

/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 觀察者(程序員1)
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class Programmer1 implements Observer{
    public Programmer1() {
        ProductManager.getInstance().registerObserver(this);
    }

    @Override
    public void updateCode() {
        //苦逼的完成需求
    }
}
複製代碼
/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 觀察者(程序員2)
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class Programmer2 implements Observer{
    public Programmer2() {
        ProductManager.getInstance().registerObserver(this);
    }

    @Override
    public void updateCode() {
        //苦逼的完成需求
    }
}
複製代碼
/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 觀察者(程序員3)
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class Programmer3 implements Observer{
    public Programmer3() {
        ProductManager.getInstance().registerObserver(this);
    }

    @Override
    public void updateCode() {
        //苦逼的完成需求
    }
}
複製代碼

觸發條件:3d

/**
 * @Author: 歡迎關注公衆號:程序員小安
 * @description: 觸發條件:老闆
 * @CreateDate: 2019/10/30
 * @Version: 1.0
 */
public class Boss {
    public void sendOrder(){
        ProductManager.getInstance().demandChanged();
    }
}
複製代碼

採用觀察者模式後,觀察者跟被觀察者之間徹底鬆耦合,當須要新增一個新的觀察者時,由於被觀察者惟一依賴的是一個實現Observer接口的列表,因此咱們能夠不修改原有被觀察者的代碼,隨時增長觀察者。同理,也能夠隨時刪除某個觀察者。 另外一方面,主要註冊的觀察者,必定會收到通知,不存在通知遺漏的狀況。 code

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
觀察者模式的優勢:

(1)具體被觀察者和具體觀察者是鬆耦合關係。

(2)觀察者模式知足「開-閉原則」。

觀察者模式的缺點:

(1)若是一個被觀察者對象有不少的直接和間接的觀察者的話,將全部的觀察者都通知到會花費不少時間。

(2)若是在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能致使系統崩潰。

(3)觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。

觀察者模式的應用場景:

(1) 對一個對象狀態的更新,須要其餘對象同步更新,並且其餘對象的數量動態可變。

(2)對象僅須要將本身的更新通知給其餘對象而不須要知道其餘對象的細節。


若有錯誤歡迎指出來,一塊兒學習。

在這裏插入圖片描述
相關文章
相關標籤/搜索