Files
2025-12-03 16:50:59 +07:00

150 lines
5.3 KiB
C#

// File : CECObserver.cs
// Creator : Xu Wenbin
// Date : 2014/4/10
// Converted to C#: 2024
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace BrewMonster
{
// class CECObservableChange
// 封装 CECObservable 的变化通知数据 / Encapsulates change notification data for CECObservable
public class CECObservableChange : IDisposable
{
public virtual void Dispose()
{
// Cleanup logic here
}
}
// class CECObserver
// 观察者基类:观察的 Model / Observer base class: observes Model
public class CECObserver<Model>
{
public virtual void OnRegistered(Model model) { }
public virtual void OnModelChange(Model model, CECObservableChange change) { }
public virtual void OnUnregister(Model model) { }
}
// class CECObservable
// 可观察者基类:被观察的 Model / Observable base class: the Model being observed
// 提供观察者注册及通知功能 / Provides observer registration and notification functionality
public class CECObservable<Model> where Model : class
{
private struct ObserverImpl
{
public CECObserver<Model> observer; // 观察者指针 / Observer pointer
public int observeTimes; // 观察次数:为正数时,收到指定次数的 OnModelChange 消息后自动取消注册,为负数时为永久,为0值时无效 / Observe times: when positive, auto-unregister after receiving specified OnModelChange messages; when negative, permanent; when 0, invalid
public bool autoDeleteOnUnregister; // 取消注册时是否自动 delete / Whether to auto-delete on unregister
public ObserverImpl(CECObserver<Model> observer, int observeTimes, bool autoDeleteOnUnregister)
{
this.observer = observer;
this.observeTimes = observeTimes;
this.autoDeleteOnUnregister = autoDeleteOnUnregister;
if (this.observeTimes == 0)
{
Debug.Assert(false, "Observer times cannot be 0");
this.observeTimes = 1; // 默认观察次数为1 / Default observe times to 1
}
}
public bool Equals(ObserverImpl rhs)
{
return this.observer == rhs.observer;
}
public bool Equals(CECObserver<Model> pObserver)
{
return this.observer == pObserver;
}
public bool WillNotObserve()
{
// 是否不再观察目标 / Whether no longer observing target
return observeTimes == 0;
}
public bool ObserveOnce()
{
// 收到一次观察消息时调用,返回是否不再观察 / Called when receiving one observe message, returns whether no longer observing
if (observeTimes > 0)
{
--observeTimes;
}
return WillNotObserve();
}
}
private List<ObserverImpl> m_observers = new List<ObserverImpl>();
protected Model AsModel()
{
return this as Model;
}
public bool IsObserverRegistered(CECObserver<Model> pObserver)
{
return m_observers.Any(impl => impl.Equals(pObserver));
}
public bool RegisterObserver(CECObserver<Model> pObserver, int observeTimes = -1, bool autoDeleteOnUnregister = false)
{
bool bRegistered = false;
if (!IsObserverRegistered(pObserver))
{
m_observers.Add(new ObserverImpl(pObserver, observeTimes, autoDeleteOnUnregister));
pObserver.OnRegistered(AsModel());
bRegistered = true;
}
return bRegistered;
}
public bool UnregisterObserver(CECObserver<Model> pObserver)
{
int index = m_observers.FindIndex(impl => impl.Equals(pObserver));
if (index >= 0)
{
return UnregisterObserverImpl(index);
}
return false;
}
public void NotifyObservers(CECObservableChange pChange)
{
Model pModel = AsModel();
for (int i = m_observers.Count - 1; i >= 0; i--)
{
ObserverImpl observerImpl = m_observers[i];
observerImpl.observer.OnModelChange(pModel, pChange);
if (observerImpl.ObserveOnce())
{
UnregisterObserverImpl(i);
}
}
}
private bool UnregisterObserverImpl(int index)
{
bool bUnRegistered = false;
if (index >= 0 && index < m_observers.Count)
{
ObserverImpl observerImpl = m_observers[index];
observerImpl.observer.OnUnregister(AsModel());
if (observerImpl.autoDeleteOnUnregister)
{
// In C#, we don't manually delete objects, but we can set to null
// The GC will handle cleanup
}
m_observers.RemoveAt(index);
bUnRegistered = true;
}
return bUnRegistered;
}
}
}