设计模式之观察者模式

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

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

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

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

EventCenter订阅管理器

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;
    }
}

添加订阅事件

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);
    }
}

触发事件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

}

三.优缺点
优点:
解耦:观察者模式可以有效地解耦主题和观察者之间的依赖关系,使得主题和观察者可以独立地变化和发展,提高了系统的灵活性和可维护性。
自动通知:当主题状态发生变化时,所有的观察者都会自动收到通知,从而可以及时地更新自己的状态,避免了手动更新和维护的麻烦。
消息传递透明:观察者模式使用事件/消息机制实现主题和观察者之间的通信,这种机制使得消息传递过程变得透明,易于理解和维护。

缺点:
性能开销:观察者模式需要维护一个观察者列表,并在主题状态发生变化时通知所有的观察者,这可能会导致一定的性能开销。
复杂性:观察者模式涉及多个对象的交互和依赖关系,这可能会增加系统的复杂性和维护难度。

你可能感兴趣的:(游戏开发,Unity,设计模式,unity,观察者模式,设计模式)