設計模式 - 觀察者模式 (Behavioral Patterns - Observer Pattern)

前言

觀察者(Observer Pattern) 定義

  • 創造一對多的連結(Subject-Observer),當被綁定的物件狀態變動的話,則通知其他物件
  • 可以保護物件不做內部破壞去通知其他物件執行功能,可以透過觀察者封裝此物件執行通知

我們只要設想,觀察者就是一個廣播機制,Subject是負責廣播的而和他同個頻道(Observer)都可以接收到他的廣播,在Observer Pattern使用物件導向(多形、封裝)的方法去實踐他

類別圖

  • 創建Subject介面負責和Observer關聯
  • Observer主要透過Subject的觸發,接收更動的訊息

範例

英雄遊戲中適合使用Observer Pattern(觀察者模式),非遊戲地圖莫屬。我們現在的遊戲業務內容是,每一張地圖都需要排隊,玩家可以訂閱此地圖(若是當地圖開放的時候(沒人在裡面)就會通知玩家)

  • 設計MapSubject負責發送通知的內容
  • 將地圖繼承MapSubject擴充發送通知的方法
  • 設計UserObserver負責接收通知內容
  • 將User繼承UserObserver擴充收通知的方法
import java.util.ArrayList;
import java.util.List;

abstract class MapSubject {
    private String mapId;

    public MapSubject(String mapId) {
        this.mapId = mapId;
    }

    private List<MapObserver> observers = new ArrayList<>();

    public void addObserver(MapObserver mapObserver) {
        observers.add(mapObserver);
    }

    public void notifyChange() {
        for (MapObserver mapObserver : observers) {
            mapObserver.update(mapId);
        }
    };
}

class MapDetail extends MapSubject {

    public MapDetail(String mapId) {
        super(mapId);
    }

    public void openMap() {
        notifyChange();
    }

}

abstract class MapObserver {
    abstract void update(String mapId);
}

class UserMapObserver extends MapObserver {

    private User user = null;

    public UserMapObserver(User user) {
        this.user = user;
    }

    @Override
    public void update(String mapId) {
        user.joinMap(mapId);
    }
}

class User {

    String name = null;
    public User(String name) {
        this.name = name;
    }

    public void joinMap(String map) {
        System.out.println(name + " get a notify from : " + map + " map");
    }
}

public class Observer {

    public static void main(String[] args) {
        User userA = new User("UserA");
        User userB = new User("UserB");
        UserMapObserver userMapObserver = new UserMapObserver(userA);
        UserMapObserver userMapObserverB = new UserMapObserver(userB);
        MapDetail map = new MapDetail("Jungle");
        map.addObserver(userMapObserver);
        map.addObserver(userMapObserverB);
        map.notifyChange();
    }
}

原始碼

結論

  • Observer Pattern(觀察者模式)用途在於若有一項物件,再更改狀態時可以通知需要被知道的物件
  • 透果兩種抽象物件之間的方法做通知(Subject & Observer)

留言

這個網誌中的熱門文章

Java Lambda Map篇

(InterviewBit) System Design - Design Cache System

設計模式 - 享元模式 (Structural Patterns - Flyweight Design Pattern)