在游戏开发中,一个数据层中的数据改变等事件会造成其它数据层的改变或者界面的改动。下面提供一种方法来解决这个问题。
解决思路是一个数据层或者界面表达出对于其它数据层中的某个数据变化的兴趣,当事件发生时,触发自身的相应代码。相当于是观察者模式,解决多个对象依赖一个对象的情况。
public interface IDataChangeObserver
{
uint GetInterestedPropId(BaseModel model);
void OnDataChange(BaseModel model, uint propId, params object[] data);
}
这是设计的接口,前者是表达的是对哪个数据的哪些事件感兴趣。后者是哪个数据层的哪个数据进行了触发,并传递一些必要的数据。
public abstract class BaseModel
{
private List<IDataChangeObserver> m_observers = new List<IDataChangeObserver>();
public void RegisterDataChange(IDataChangeObserver observer)
{
if (!m_observers.Contains(observer)) m_observers.Add(observer);
}
public void UnRegisterDataChange(IDataChangeObserver observer)
{
m_observers.Remove(observer);
}
public void OnDataChange(uint propId, params object[] data)
{
foreach (var observer in m_observers)
{
if ((observer.GetInterestedPropId(this) & propId) != 0)
{
try
{
observer.OnDataChange(this, propId, data);
}
catch (Exception e)
{
Console.WriteLine($"{this} onDataChangeError {e}");
}
}
}
}
}
这是数据层的设计,能在其它代码中注册这个数据层的变化并且注销,当数据变化时能够下发到注册的观察者中。
public class TestModel1 : BaseModel, IDataChangeObserver
{
public void Init()
{
Test.testModel2.RegisterDataChange(this);
}
public void UnInit()
{
Test.testModel2.UnRegisterDataChange(this);
}
public uint GetInterestedPropId(BaseModel model)
{
if (model == Test.testModel2)
{
return TestModel2.propId1 | TestModel2.propId2;
}
return 0;
}
public void OnDataChange(BaseModel model, uint propId, params object[] data)
{
if (model == Test.testModel2)
{
if (propId == TestModel2.propId1)
{
Console.WriteLine(data[0]);
}
}
}
}
public class TestModel2 : BaseModel
{
public static uint propId1 = 1 << 0;
public static uint propId2 = 1 << 1;
public static uint propId3 = 1 << 2;
public void TriggerDataChange()
{
OnDataChange(propId1, new object[]{"fasdfas", "mompimim" });
}
}
public static class Test
{
public static TestModel1 testModel1 = new TestModel1();
public static TestModel2 testModel2 = new TestModel2();
public static void Main()
{
testModel1.Init();
testModel2.TriggerDataChange();
testModel1.UnInit();
}
}
这是一些测试代码。