iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
Software Development

從生活中認識Design Pattern系列 第 28

[Day28] 觀察者模式 | Observer Pattern

同步分享於個人blog

  • 定義


多個物件之間存在著一對多的依賴關係,當一個物件發生改變時,所有跟他有關的物件都會被通知且更新。

現實生活中就有許多觀察者模式的案例,例如:訂閱youtuber,發布新影片就會接收到通知;加入Line官方帳號,會接收到優惠訊息...等等。

  • Observer Pattern 成員


name description
Subject 抽象目標,提供保存觀察者物件的集合以及增加觀察者物件的方法、刪除觀察者物件的方法以及通知所有觀察者的抽象方法。
ConcreteSubject 具體目標,實作抽象目標中的通知方法。具體目標內部發生改變時會通知所有加入的觀察者物件。
Observer 抽象觀察者,可以是抽象類別或是介面。含有更新自己的抽象方法。
ConcreteObserver 實作抽象觀察者,在目標更改狀態時接收通知並更改自身狀態。

o1

  • Observer Pattern 實作


就拿現在很紅的Youtuber來做範例,Peeta葛格是一個Youtuber,我們訂閱了之後,就可以接收到他發片的通知,所以Peeta是目標,而我們是觀察者。廠商也訂閱了Peeta,他想知道Peeta發片時是不是葉配影片,所以廠商也是觀察者。

import java.util.*;

enum Type { // 建立列舉方便等等程式使用
    BUSINESS, VLOG
}

//抽象目標:分別有存放觀察者的集合以及增加、刪除、通知觀察者的方法
abstract class Subject {
    protected List<Observer> observers = new ArrayList<Observer>();   
    //增加觀察者
    public void add(Observer observer) {
        observers.add(observer);
    }    
    //刪除觀察者
    public void remove(Observer observer) {
        observers.remove(observer);
    }   
    public abstract void notifyObserver(Type type); //通知觀察者
}
//實體目標 Peeta葛格:實作抽象目標,通知觀察者的方法。
class YoutuberPeeta extends Subject {
    public void notifyObserver(Type type) {
        String videoType = null;
        switch(type){
            case BUSINESS:
                videoType = "葉配";
                break;
            case VLOG:
                videoType = "vlog";
                break;
        }
        System.out.println("Peeta 發布新" + videoType + "影片");
        System.out.println("--------------");       
       
        for(Object obs:observers) {
            ((Observer)obs).response(type);
        }
       
    }          
}

//抽象觀察者:定義接收到目標時的方法。
interface Observer {
    void response(Type type); //反應
}
//實體觀察者 粉絲
class Fans implements Observer {
    public void response(Type type) {
        switch(type){
            case BUSINESS:
                System.out.println("紛絲看到葉配表示傷心!");
                break;
            case VLOG:
                System.out.println("紛絲看到VLOG覺得有趣!");
                break;
        }
    }
}
//實體觀察者:廠商
class Vendor implements Observer {
    public void response(Type type) {
                switch(type){
            case BUSINESS:
                System.out.println("廠商看到葉配覺得開心!");
                break;
            case VLOG:
                System.out.println("廠商看到VLOG表示為啥不是葉配!");
                break;
        }
    }
}

// Client分別建立目標及兩個觀察者,而目標在發布新影片時會同時通知兩個觀察者
public class ObserverPattern {
    public static void main(String[] args) {
        Subject subject = new YoutuberPeeta();
        Observer obs1 = new Fans();
        Observer obs2 = new Vendor();
        subject.add(obs1);
        subject.add(obs2);
        subject.notifyObserver(Type.BUSINESS);
        System.out.println();    
        subject.notifyObserver(Type.VLOG);
    }
}

output

Peeta 發布新葉配影片
--------------
紛絲看到葉配表示傷心!
廠商看到葉配覺得開心!

Peeta 發布新vlog影片
--------------
紛絲看到VLOG覺得有趣!
廠商看到VLOG表示為啥不是葉配!
  • 小結


Observer Pattern的目標

多個物件之間存在著一對多的依賴關係,當一個物件發生改變時,所有跟他有關的物件都會被通知且更新。

Observer Pattern的成員
Subject:抽象目標,提供保存觀察者物件的集合以及增加觀察者物件的方法、刪除觀察者物件的方法以及通知所有觀察者的抽象方法。
ConcreteSubject:具體目標,實作抽象目標中的通知方法。具體目標內部發生改變時會通知所有加入的觀察者物件。
Observer:抽象觀察者,可以是抽象類別或是介面。含有更新自己的抽象方法。
ConcreteObserver:實作抽象觀察者,在目標更改狀態時接收通知並更改自身狀態。
Observer Pattern的優缺點
優點
1. 降低目標與觀察者間的耦合關係,兩者之間為抽象耦合關係。
2. 目標與觀察者間建立了一套觸發機制。
缺點
1. 目標與觀察者間的依賴並無完全切除。
2. 當觀察者物件多時,會影響效能。
Observer Pattern的使用時機
1. 物件之間存在一對多的關係,一個物件狀態改變會影響其他物件時。
  • 範例程式碼


範例:Observer Pattern 實作

  • References


觀察者模式 (Observer Pattern)
觀察者模式


上一篇
[Day27] 備忘錄模式 | Memento Pattern
下一篇
[Day29] 策略模式 | Strategy Pattern
系列文
從生活中認識Design Pattern30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言