设计模式之观察者模式

一.介绍

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

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

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

}

三.优缺点

优点:

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

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

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

缺点:

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

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

相关推荐
WaaTong4 小时前
《重学Java设计模式》之 单例模式
java·单例模式·设计模式
WaaTong6 小时前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
霁月风6 小时前
设计模式——观察者模式
c++·观察者模式·设计模式
暗黑起源喵9 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
小春熙子13 小时前
Unity图形学之Shader结构
unity·游戏引擎·技术美术
Sitarrrr16 小时前
【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
3d·unity
极梦网络无忧16 小时前
Unity中IK动画与布偶死亡动画切换的实现
unity·游戏引擎·lucene
wrx繁星点点16 小时前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
金池尽干18 小时前
设计模式之——观察者模式
观察者模式·设计模式
也无晴也无风雨18 小时前
代码中的设计模式-策略模式
设计模式·bash·策略模式