iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0

GoF對於Observer的定義為
「在物件之間定一個一對多的的連結方法,當一個物件變換狀態時,其它關連的物件都會自動收到通知」

你也可以這樣說—Observer Objects Observe Observable Objects.(觀察者物件觀察可觀察的物件們)
講個更具體的,你可以想像成自己在Youtube訂閱一個你喜愛的Youtuber,之後你就會在訂閱內容的部分看到對方發出的最新影片,而不用去花費心力去翻閱每一個Youtuber的更新狀況。

而Obsever的實作方式有分成推與拉這兩種,這次會主要以拉的案例為主,有興趣可以點下面的連結看推的例子

IObserver.cs

namespace LinXuan.DesignPattern.Example.Observer 
{ 
    public interface IObserver 
    { 
        public void ObserverUpdate(); 
    } 
}

ISubject.cs

namespace LinXuan.DesignPattern.Example.Observer
{
    public interface ISubject
    {
        public void Attach(IObserver observer);//想要訂閱此Observer時,就將其記錄下來
        public void Detach(IObserver observer);//取消訂閱
        public void Notify();//更新擁有的訂閱者
    }
}

Observers.cs

using UnityEngine;

namespace LinXuan.DesignPattern.Example.Observer 
{ 
    public class FooObserver : IObserver 
    { 
        private string m_ObjectState; 
        private FooSubject m_Subject = null;

        public FooObserver(FooSubject fooSubject) 
        { 
            m_Subject = fooSubject; 
        }

        public void ObserverUpdate() 
        { 
            Debug.Log("FooObserver.Update"); 
        }

        public void ShowState()  //當呼叫此function時才顯示當前狀態 
        { 
            Debug.Log("FooObserver: Subject " + m_ObjectState); 
        } 
    }

    public class BarObserver : IObserver 
    { 
        private FooSubject m_Subject = null;

        public BarObserver(FooSubject fooSubject) 
        { 
            m_Subject = fooSubject; 
        }

        public void ObserverUpdate() 
        { 
            Debug.Log("BarObserver.Update"); 
            Debug.Log("BarObserver: Subject " + m_Subject.GetState());  //在這邊就顯示當前狀態 
        } 
    } 
}

FooSubject.cs

using System.Collections.Generic;

namespace LinXuan.DesignPattern.Example.Observer 
{ 
    public class FooSubject : ISubject 
    { 
        List<IObserver> m_Observers = new List<IObserver>(); //儲存想要關注的Observer的地方
        string m_SubjectState;

        public void SetState(string state) 
        { 
            m_SubjectState = state; 
            Notify(); 
        }

        public string GetState() 
        { 
            return m_SubjectState; 
        }

        public void Attach(IObserver observer) 
        { 
            m_Observers.Add(observer); 
        }

        public void Detach(IObserver observer) 
        { 
            m_Observers.Remove(observer); 
        }

        public void Notify() 
        { 
            foreach (IObserver observer in m_Observers) 
            { 
                observer.ObserverUpdate(); 
            } 
        } 
    } 
}

ObserverTest_PullTest.cs

using UnityEngine;

namespace LinXuan.DesignPattern.Example.Observer 
{ 
    public class ObserverTest_PullTest : MonoBehaviour 
    { 
        private void Start() 
        { 
            FooSubject fooSubject = new FooSubject(); 
            FooObserver fooObserver = new FooObserver(fooSubject); 
            BarObserver barObserver = new BarObserver(fooSubject);

            fooSubject.Attach(fooObserver); 
            fooSubject.Attach(barObserver); 
            fooSubject.SetState("Subject state 1."); 
            fooObserver.ShowState(); 
        } 
    } 
}

輸出如下
https://ithelp.ithome.com.tw/upload/images/20221001/20151894judaLLgScK.png

參考資料

Push, pull mechanism observer pattern
The Observer Pattern
設計模式與遊戲開發的完美結合(暢銷回饋版)


上一篇
Day 16:Factory模式(二)
下一篇
Day 18:Observer模式(二)
系列文
如何在Unity裡寫出具有一定擴充性的遊戲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言