设计模式之观察者模式

11 篇文章 0 订阅
4 篇文章 0 订阅

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

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

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

}

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

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

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
观察者模式是一种常用的设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,它的所有观察者都会收到通知并更新自己的状态。 在C++中,观察者模式通常由一个抽象主题类和多个具体观察者类组成。抽象主题类中定义了添加、删除和通知观察者的接口,具体观察者类实现了更新自身状态的方法。 以下是一个简单的观察者模式示例: ```c++ #include <iostream> #include <vector> class Observer { public: virtual void update() = 0; }; class Subject { public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { for (auto it = observers.begin(); it != observers.end(); ++it) { if (*it == observer) { observers.erase(it); break; } } } void notify() { for (auto observer : observers) { observer->update(); } } private: std::vector<Observer*> observers; }; class ConcreteObserver1 : public Observer { public: void update() override { std::cout << "ConcreteObserver1 updated" << std::endl; } }; class ConcreteObserver2 : public Observer { public: void update() override { std::cout << "ConcreteObserver2 updated" << std::endl; } }; int main() { Subject subject; ConcreteObserver1 observer1; ConcreteObserver2 observer2; subject.attach(&observer1); subject.attach(&observer2); subject.notify(); subject.detach(&observer1); subject.notify(); return 0; } ``` 在上面的示例中,Subject类是抽象主题类,Observer类是抽象观察者类,ConcreteObserver1和ConcreteObserver2是具体观察者类。当Subject对象状态发生变化时,它会通知所有观察者更新自己的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值