设计模式 --- 观察者模式

观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。

优点:

​​1.解耦性强​​

​​观察者(订阅者)与主题(发布者)通过抽象接口通信,不直接依赖具体实现,​​修改主题或观察者的代码时,无需影响对方,提升代码可维护性。

2.​​动态订阅机制​​

​​观察者可随时注册或注销,运行时灵活调整事件响应,支持热插拔功能,增强系统扩展性。

3.​​一对多通信高效​​

一个主题状态变化可同时通知多个观察者,避免重复调用逻辑,提升事件处理效率。

​​4.支持事件驱动架构​​

通过事件总线(Event Bus)实现全局通信, ​​简化跨模块通信,适合复杂系统交互。

缺点:

1.​性能开销​​:

高频事件(如每帧更新)或大量观察者时,遍历通知列表耗时(物理引擎的CollisionEvent在百个对象碰撞时,触发千次通知)。

​​优化​​

1.使用事件合并(如积累多次位置更新后批量通知)。

2.异步处理(将事件推送到队列,分帧处理)。

2.​​内存泄漏风险​​:

​​观察者未正确注销时,Subject(主题者)持有其引用导致无法回收(Unity中,UI面板销毁前未取消订阅事件)。

​​优化​​

使用弱引用(WeakReference)或者使用扩展方法在MonoBehaviour绑定取消事件注册的方法,使其在OnDestroy时调用取消注册方法。

cs 复制代码
public static void UnregisterOnDestroy(this MonoBehaviour obj, Action unsubscribe) {
    obj.gameObject.AddComponent<OnDestroyDispatcher>().OnDestroyEvent += unsubscribe;
}

class OnDestroyDispatcher : MonoBehaviour {
    public event Action OnDestroyEvent;
    void OnDestroy() => OnDestroyEvent?.Invoke();
}

注:弱引用的使用 (会加一篇Unity中弱引用的测试使用的文章)。

3.​​事件顺序不可控​​:

​​观察者处理事件的顺序依赖注册顺序,可能导致逻辑错误。

​​优化 ​​:

引入优先级字段,按优先级排序观察者。

4.​调试困难​​:

​​问题​​:事件流分散,难以追踪事件触发源头和传递链路。

​​优化 ​​:

添加事件日志:记录每个事件的发布者和订阅者。

说明例子:

1.UML图:

2.实现:

1.实现Subject(主题者)基类:

cs 复制代码
    public abstract class Subject
    {
        List<Observer> m_Observers = new List<Observer>();

        //加入观察者
        public void Attach(Observer theObserver)
        {
            m_Observers.Add(theObserver);
        }

        //删除观察者
        public void Detach(Observer theObserver)
        {
            m_Observers.Remove(theObserver);
        }

        //通知所有观察者
        public void Notify()
        {
            foreach (Observer theObserver in m_Observers)
            {
                theObserver.Update();
            }
        }
    }

2.实现Observer(观察者)基类:

cs 复制代码
    public abstract class Observer
    {
        public abstract void Update();
    }

3.实现具体Subject:

cs 复制代码
    public class ConcreteSubject : Subject
    {
        string m_SubjectState;

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

        public string GetState()
        {
            return this.m_SubjectState;
        }
    }

4.实现具体Observer:

cs 复制代码
   //实现Observer1
   public class ConcreteObserver1 : Observer
   {

       ConcreteSubject m_Subject = null;

       public ConcreteObserver1(ConcreteSubject theSubject)
       {
           this.m_Subject = theSubject;
       }

       public override void Update()
       {
           Debug.Log("ConcreteObserver1.Update");
           //获取Subject状态
           Debug.Log("ConcreteObserver1 : Subject 当前主题:" + m_Subject.GetState());
       }
   }

   //实现Observer2
   public class ConcreteObserver2 : Observer
   {

       ConcreteSubject m_Subject = null;

       public ConcreteObserver2(ConcreteSubject theSubject)
       {
           this.m_Subject = theSubject;
       }

       public override void Update()
       {
           Debug.Log("ConcreteObserver2.Update");
           //获取Subject状态
           Debug.Log("ConcreteObserver2 : Subject 当前主题:" + m_Subject.GetState());
       }
   }

游戏中使用场景:

​​1.成就/统计系统​​ :监听关键游戏事件(击杀、死亡、收集)--->玩家击杀Boss后解锁成就。

​​2.UI更新 ​​:将UI元素与游戏数据解耦--->血量变化时自动刷新血条UI。

​​3.跨系统通信​​ :避免系统间直接引用--->背包系统物品使用后通知技能系统。

​​4.AI行为触发​​ :基于事件触发的敌人反应---->玩家进入警戒范围触发敌人警报。

​​5.网络同步​​:将本地事件广播给其他客户端--->玩家位置同步事件。

总结:

观察者模式的核心价值​​在于解耦和动态通信,但其性能、内存和调试问题需谨慎处理。

在游戏开发中,观察者模式适用于以下场景:

1.需要松耦合的跨系统通信。

2.需要动态处理大量事件类型

3.需要支持模块化扩展(如MOD系统)。

参考书籍:

《Hands-On Game Development Patterns with Unity 2019》

《设计模式与游戏完美开发》

相关推荐
Zane19942 天前
一个 new 就能创建对象,为什么还要拆出单例、工厂、建造者、原型四种模式?
设计模式
怕浪猫3 天前
一行命令复刻爆款视频,我把 Hypit 从安装跑到了出片
人工智能·设计模式·程序员
Zane19943 天前
函数式编程里的函数,其实不是你天天写的那个函数——三大编程范式的边界在哪
设计模式
Zane19944 天前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..4 天前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang1504 天前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)5 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki5 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅666 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa6 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio