C#基础16:事件与观察者模式

前文:https://blog.csdn.net/Jaihk662/article/details/96895681(委托)

一、事件与委托

其实事件就是委托的一种升级版,和委托的不同如下:

  • 在原有的委托变量的基础上多一个 event 关键字,这个委托变量就称为事件;
  • 在其它类中,事件只能使用 +=、-= 来注册方法,而不能使用 = 为事件关联方法,相对于委托更加安全

一个例子如下(你也可以把它当成委托的一个应用场景):

功能:当你按下键盘K后,可以模拟每月的自动续费功能,返回一个消费账单

当你按下Z键后,可以清除当前所有的自动续费

PlayerCtro.cs:

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

public delegate void Func();         //声明一个委托
public class PlayerCtro : MonoBehaviour
{
    public Func func;         //定义一个事件
    public static PlayerCtro instance;

    private void Awake()
    {
        instance = this;                //继承于Mono的脚本单例写法,如果不是U3D环境,可以自己写个单例
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.K))            //当按下"K"键后
        {
            Debug.Log("你本月的消费账单如下:");
            func();
        }
        if (Input.GetKeyDown(KeyCode.Z))
        {
            DelFunc();
            if(func == null)                //如果委托没有绑定任何方法
                Debug.Log("你已成功取消所有的自动续费功能");
        }
    }
    public void DelFunc()           //清空委托绑定的所有的方法,需要 using System;
    {
        Delegate[] delFunc = func.GetInvocationList();
        for (int i = 0; i < delFunc.Length; i++)
            func -= delFunc[i] as Func;
    }
}

Month.cs:

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

public class Month : MonoBehaviour
{
    private void Start()
    {
        PlayerCtro.instance.func += Yueka;      //玩家开启月卡自动续费...
        //PlayerCtro.instance.func = Yueka;         非法,事件只能在声明的类中使用"="号
    }

    public void Yueka()
    {
        Debug.Log("月卡:¥30");
    }
}

二、观察者模式

设计模式:为了解决一些固定问题的代码套路

观察者设计模式(Observer):又称“发布-订阅模式”,是一种一对多的依赖关系,多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,通知所有观察者

其实上面事件的例子,也可以算作一个非常简单的观察者模式的例子,另一个例子如下:

Subject.cs:

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

public delegate void Func(string hint);         //声明一个委托
public class Subject : MonoBehaviour
{
    public Func func;         //定义一个事件
    public int index;
    public static Subject instance;

    private void Awake()
    {
        instance = this;                //继承于Mono的脚本单例写法,如果不是U3D环境,可以自己写个单例
    }
    private void Start()
    {
        index = 905;
    }
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.K))            //当按下"K"键后,模拟下一集更新
        {
            func(string.Format("名侦探柯南第 {0} 集已经更新", ++index));
        }
    }
}

Observer1.cs:

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

public class Observer1 : MonoBehaviour
{
    private void Start()
    {
        Subject.instance.func += Show;          //模拟订阅
        Debug.Log("你已经成功订阅视频:“名侦探柯南”");
    }

    public void Show(string hint)
    {
        Debug.Log("收到新消息" + hint);
    }
}

运行结果:

原创文章 1134 获赞 1439 访问量 61万+

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/96997290