Observer pattern

在遊戲中,會發生很多事,例如擊敗一個敵人,玩家升級等,如果直接將這些行為直接在各個物件中執行,會增加很多依賴,當程式碼成長到一定程度時,會變得很難維護。

觀察者模式(Observer pattern)通常會用來解決此問題。它使用一種one-to-many依賴(dependency),讓你的物件之間的溝通可以保持在一種低耦合(loosely coupled)的關係,當一個物件的狀態改變時,會自動通知所有想要接收此訊息的物件。例如廣播系統,廣播會向外發送音樂給收聽者,廣播不需要知道誰在收聽,它只要使用固定的頻道發送音樂即可,而收聽者只需要將頻道調整到該廣播系統的頻道即可收到音樂。

  • 發送消息的物件稱為subject
  • 其他接收此消息的物件稱為observers

優點:

  • 發送消息的物件(subject)與接收此消息的物件(observers)解耦(Loose coupling)
    • 發送消息的物件不需要知道關於接收此消息的物件的資訊,它只需要負責將消息發送出去;
    • 接收此消息的物件會有一個發送消息物件的依賴,但是接收此消息的物件之間互相不知道彼此
  • 將observer需要對訊息做出反應的邏輯放到對應的observer中,讓他們各自維護。變得較容易測試與除錯
  • 非常適合使用者介面(User Interface),MVPMVC patterns就是使用觀察者模式(Observer pattern)

缺點:

  • 增加程式複雜度,
  • 如果要刪除Subject的話會比較麻煩
  • Observer仍然會對Subject有依賴,
    • 可以使用一個static EventManager除去
  • 會消耗一些效能

在C#中已經有實作Observer pattern => Event

  • publisher(即subject):有一個或多個event,在執行時,會將訊息發送給註冊這些event的物件
  • observers:這些物件會有一些event handler的方法,當publisher發送訊息時,便會執行對應的event handler方法

以下是一個最簡單的例子
Subject有一個 event ThingHappened,它暴露給其他物件讓它們可以註冊

1
2
3
4
5
6
7
8
9
public class Subject
{
public event Action ThingHappened;

public void DoThing()
{
ThingHappened?.Invoke();
}
}

Observer有一個Subject依賴,用來註冊;並且有一個OnEventHandler,當Subject發送訊息時,便會執行這個方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Observer
{
private Subject subjectToObserve;

public Observer(Subject subject)
{
subjectToObserve = subject;
subjectToObserve.ThingHappened += OnEventHandle;
}

private void OnEventHandler()
{
// any logic that responds to event goes here
Debug.Log("Observer responds");
}
}

Reference: https://unity.com/how-to/create-modular-and-maintainable-code-observer-pattern

評論