设计模式之观察者模式

一.介绍

观察者模式是一种软件设计模式,它允许对象之间定义一对多的依赖关系,当一个对象状态发生变化时,所有依赖于它的对象都会得到通知并被自动更新。这种模式可以有效地解耦主题和观察者之间的依赖关系,提高系统的灵活性和可维护性。

在观察者模式中,主题和观察者是独立的实体。主题负责维护一个观察者列表,并通知所有的观察者关于状态的变化。观察者负责监听主题的状态变化,并在收到通知时更新自己的状态。具体观察者则是观察者的子类,它实现了更新自己状态的具体逻辑。

在游戏开发中,观察者模式可以用于实现多种功能。例如,在角色状态变化方面,我们可以将多个监听器绑定到同一个事件上,当事件发生时,所有监听器都会收到通知并执行相应的操作。例如,当角色血量发生变化时,所有绑定到该事件的监听器都会收到通知,并执行相应的操作,如播放声音、更新UI等。

二.实现

设置一个管理类来控制事件订阅注册与注销。

EventCenter订阅管理器

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class EventCenter
{
    private static EventCenter instance;//EventCenter使用单例模式
    private Dictionary<string,IEventInfo> _eventDic = new Dictionary<string, IEventInfo>();//创建事件字典(事件名,订阅列表)
    public static EventCenter Instance
    {
        get{
            if(instance == null)
            {
                instance = new EventCenter();
            }
            return instance;
        }
    }
    public void AddEventListener(string name,UnityAction action)//添加订阅消息
    {
        if(_eventDic.ContainsKey(name))//事件名是否存在
        {
            (_eventDic[name] as EventInfo).actions+=action;//存在,向该事件名的订阅列表添加该action
        }
        else
        {
            _eventDic.Add(name,new EventInfo(action));//不存在,创建新的事件名和订阅列表
        }
    }
    public void EventTrigger(string name) //通知信息
    {
        if(_eventDic.ContainsKey(name))//判断是否存在事件名
        {
            if((_eventDic[name] as EventInfo).actions != null)//该事件名是否有action订阅
            {
                (_eventDic[name] as EventInfo).actions.Invoke();//通知所有订阅该时间的action
            }
        }
    }
    public void RemoveEventListener(string name,UnityAction action)//取消订阅
    {
        if(_eventDic.ContainsKey(name))//判断是否存在事件名
        {
            (_eventDic[name] as EventInfo).actions -= action;//取消该事件下的action订阅
        }
    }

    public void AddEventListener<T>(string name,UnityAction<T> action)//和上面函数功能一致,可携带参数
    {
        if(_eventDic.ContainsKey(name))
        {
            (_eventDic[name] as EventInfo<T>).actions+=action;
        }
        else
        {
            _eventDic.Add(name,new EventInfo<T>(action));
        }
    }
    public void EventTrigger(string name) 
    {
        if(_eventDic.ContainsKey(name))
        {
            if((_eventDic[name] as EventInfo<T>).actions != null)
            {
                (_eventDic[name] as EventInfo<T>).actions.Invoke();
            }
        }
    }
    public void RemoveEventListener(string name,UnityAction action)
    {
        if(_eventDic.ContainsKey(name))
        {
            (_eventDic[name] as EventInfo<T>).actions -= action;
        }
    }
    public void Clear()//清空所有订阅
    {
        _eventDic.Clear();
    }

}

public interface IEventInfo //创建接口,让类继承接口来实现便于实现多中类型订阅列表
{

}

public class EventInfo:IEventInfo //不带参数的订阅列表
{
    public UnityAction actions;
    public EventInfo(UnityAction action)
    {
        actions += action;
    }
}

public class EventInfo<T>:IEventInfo //带参数的订阅列表,使用了泛型,可以传递多种数据类型的参数
{
    public UnityAction<T> actions;
    public EventInfo(UnityAction<T> action)
    {
        actions += action;
    }
}

添加订阅事件

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager : MonoBehaviour
{
    public PlayerStatBar playerStatBar;//角色血量
    private void Start()
    {
        EventCenter.Instance.AddEventListener("EventTakeDamage",OnHealthEvent)
    }
    private void OnHealthEvent(Character character)//获取角色当前的血量与最大血量比,并调用playerStatBar.OnHealthChange,更新血量UI
    {
        var persentage = character.currentHP / character.maxHP;

        playerStatBar.OnHealthChange(persentage);
    }
}

触发事件

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Character : MonoBehaviour
{
    public void TakeDamage(Attack attacker)//触发受伤
    {
        EventCenter.instance.EventTrigger<Character>("EventTakeDamage",this);//触发消息
    }

}

三.优缺点

优点:

解耦:观察者模式可以有效地解耦主题和观察者之间的依赖关系,使得主题和观察者可以独立地变化和发展,提高了系统的灵活性和可维护性。

自动通知:当主题状态发生变化时,所有的观察者都会自动收到通知,从而可以及时地更新自己的状态,避免了手动更新和维护的麻烦。

消息传递透明:观察者模式使用事件/消息机制实现主题和观察者之间的通信,这种机制使得消息传递过程变得透明,易于理解和维护。

缺点:

性能开销:观察者模式需要维护一个观察者列表,并在主题状态发生变化时通知所有的观察者,这可能会导致一定的性能开销。

复杂性:观察者模式涉及多个对象的交互和依赖关系,这可能会增加系统的复杂性和维护难度。

相关推荐
呆呆敲代码的小Y1 小时前
【Unity 实用工具篇】| UX Tool 工具 快速上手使用,提高日常开发效率
游戏·unity·游戏引擎·游戏程序·ux
世洋Blog1 小时前
Unity开发微信小程序-避开新InputSystem有关坑
unity·微信小程序
一路往蓝-Anbo13 小时前
STM32单线串口通讯实战(五):RTOS架构 —— 线程安全与零拷贝设计
c语言·开发语言·stm32·单片机·嵌入式硬件·观察者模式·链表
简简单单OnlineZuozuo15 小时前
提示架构:设计可靠、确定性的AI系统
人工智能·unity·架构·游戏引擎·基准测试·the stanford ai·儿童
蔺太微16 小时前
桥接模式(Bridge Pattern)
设计模式·桥接模式
zhaokuner17 小时前
14-有界上下文-DDD领域驱动设计
java·开发语言·设计模式·架构
Geoking.20 小时前
【设计模式】抽象工厂模式(Abstract Factory)详解:一次创建“一整套产品”
设计模式·抽象工厂模式
zhaokuner1 天前
12-深层模型与重构-DDD领域驱动设计
java·开发语言·设计模式·架构
不加糖4351 天前
设计模式 -- 适配器 & 策略模式
python·设计模式
__万波__1 天前
二十三种设计模式(十九)--备忘录模式
java·设计模式·备忘录模式