Unity中基于观察者模式的原理实现事件绑定

两种方法都可以实现对对象中数据的绑定,第一种通过接口实现,第二种通过委托实现,都需要手动添加绑定,第一种手动触发对应事件,第二种自动触发对应事件。

一、通过接口实现

1.首先定义需要触发的事件的接口

public interface IWBindable
{
    void onBindingUpdate(Wbindable vo);
}

2.定义值对象的基类,实现事件的注册注销等

public class Wbindable
{
    private List<IWBindable> m_listCallBacks = new List<IWBindable>();
    public bool hasBinding(IWBindable receiver)
    {
        foreach (IWBindable wkr in m_listCallBacks)
        {
            if (wkr == receiver)
            {
                return true;
            }
        }
        return false;
    }
    public void addBinding(IWBindable receiver)
    {
        if (hasBinding(receiver))
        {
            return;
        }
        m_listCallBacks.Add(receiver);
    }

    public void removeBinding(IWBindable receiver)
    {
        List<IWBindable> l = new List<IWBindable>(m_listCallBacks);
        foreach (IWBindable wkr in l)
        {
            if (wkr == null || wkr == receiver)
            {
                m_listCallBacks.Remove(wkr);
            }
        }
    }
    public void notifyBindings()
    {
        List<IWBindable> l = new List<IWBindable>(m_listCallBacks);
        foreach (IWBindable wkr in l)
        {
            if (wkr == null)
            {
                m_listCallBacks.Remove(wkr);
            }
            else
            {
                wkr.onBindingUpdate(this);
            }
        }
    }
}

3.测试代码跑起来,创建一个具体的值对象类,实例化出来后通过notifyBindings方法可以获取该类实例的当前字段的值,而onBindingUpdate方法中决定你想监听哪个值或者触发一些其他的事件。

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

public class ItemWbindable : Wbindable
{
    public string name;
    public int Id;
}
public class BindTest : MonoBehaviour, IWBindable
{
    // Use this for initialization
    void Start()
    {
        ItemWbindable vo = new ItemWbindable();
        vo.name = "aaa";
        vo.Id = 1;
        vo.addBinding(this);
        vo.notifyBindings();
    }
   public void onBindingUpdate(Wbindable vo)
    {
        ItemWbindable m_vo = (ItemWbindable)vo;
        Debug.Log(string.Format("变化后的值:{0}----{1}", m_vo.name, m_vo.Id));
        //监听对象的值的变化or do sthing
    }
}

二、通过委托实现

1.同样的实现值对象基类,注册注销等方法

public class Model {
    private Type m_thisType;
    public delegate void BindingDataDelegate(object objData);
    private Dictionary<string, List<BindingDataDelegate>> m_dicDataBinding = new Dictionary<string, List<BindingDataDelegate>>();

    public Model()
    {
        m_thisType = GetType();
    }

    public void addDataBinding(BindingDataDelegate callBack, string propertyName)
    {
        List<BindingDataDelegate> methods = null;
        if (m_dicDataBinding.ContainsKey(propertyName))
        {
            methods = m_dicDataBinding[propertyName];
        }
        else
        {
            methods = new List<BindingDataDelegate>();
            m_dicDataBinding.Add(propertyName, methods);
        }
        methods.Add(callBack);
    }
    public void updateBinding(string propertyName)
    {
        if (m_dicDataBinding.ContainsKey(propertyName))
        {
            //Dictionary<string, List<BindingDataDelegate>> allBindings = new Dictionary<string, List<BindingDataDelegate>>(m_dicDataBinding);
            object objData = _getPropertyValue(propertyName);
            List<BindingDataDelegate> bds = new List<BindingDataDelegate>(m_dicDataBinding[propertyName]);
            foreach (BindingDataDelegate m in bds)
            {
                m(objData);
            }
        }
    }
    public void updateBinding(string propertyName, object customParam)
    {
        if (m_dicDataBinding.ContainsKey(propertyName))
        {
            List<BindingDataDelegate> bds = new List<BindingDataDelegate>(m_dicDataBinding[propertyName]);
            foreach (BindingDataDelegate m in bds)
            {
                m(customParam);
            }
        }
    }
    public void removeDataBinding(BindingDataDelegate callBack, string propertyName)
    {
        List<BindingDataDelegate> methods = null;
        if (m_dicDataBinding.ContainsKey(propertyName))
        {
            methods = m_dicDataBinding[propertyName];
            if (methods.Contains(callBack))
            {
                methods.Remove(callBack);
            }
        }
    }
    private object _getPropertyValue(string strName)
    {
        object value = null;
        FieldInfo fi = m_thisType.GetField(strName);
        if (fi != null)
        {
            value = fi.GetValue(this);
        }
        else
        {
            //PropertyInfo pi=m_thisType.GetProperty(strName);
            value = this.GetType().GetProperty(strName).GetValue(this, null);

        }
        return value;
    }
}

2.值对象具体类

public class ItemModel : Model {
    string str;
    public string Str
    {
        get { return str; }
        set { str = value; updateBinding("Str"); }
    }
}

3.测试代码

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

public class DataBindTest : MonoBehaviour {

	void Start () {
        ItemModel model = new ItemModel();
        model.addDataBinding(fun, "Str");
        model.Str = "新的值";
    }
    void fun(object para) {

        Debug.Log(para);
        //do sthing
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值