Observer和Unity

Tulenber 26 June, 2020 ⸱ Intermediate ⸱ 3 min ⸱ 2019.4.0f1 ⸱

让我们向我们的存 钱罐添加另一个重要的模板(以及它们是什么)。

观察者是构建轻量级松散耦合系统必不可少的模板,从体系结构的角度来看,它可以显着简化寿命。当我们考虑一个新的输入系统时,我们已经面临使用观察者的问题,但并未专注于此。Unity有多个实现此模板的选项,老实说,一个没有准备的用户可能会引起一些混乱,所以让我们从基础上看一下所有内容。

理论

粗略地说,观察者将世界分为两种类型的对象:发布者和订阅者。订阅者可以订阅(和取消订阅)以接收来自发布者的事件通知,发布者将事件通知所有签署者。因此,在对象之间没有刚性连接的情况下为对象之间的交互创造了机会。在罗伯特·尼斯特罗姆(Robert Nystrom)的本文本章中,可以找到更多的理论。

Unity

delegate关键字是实现观察者的主要机制。Unity(更确切地说是.Net)还提供event类型的对象以确保更高的安全性。

Delegate

我们可以说delegate是一种指向函数而不是值的变量。如果您曾经听说过C ++,那么它就是函数指针,这是一种非常常见的机制。

值得一提的第二个属性是,向该指针添加多个函数将导致它们的执行调用此指针,这使其成为我们在本文中考虑的模板的实现。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class DelegateTest {
    // 声明一个指向void类型的函数的指针,并带有一个string类型的参数
    public delegate void Print(string val);

    public DelegateTest()
    {
        // 具有上述签名的函数分配给p
        Print p = PrintValue;
        // 添加另一个订户执行
        p += PrintData;
        // 呼叫所有用户p
        p("Delegate");
    }

    private void PrintData(string s)
    {
        Console.WriteLine("PrintData " + s);
    }

    public void PrintValue(string s)
    {
        Console.WriteLine("PrintValue " + s);
    }
}

执行结果:

1
2
PrintValue Delegate
PrintData Delegate

System.Action

您还应该熟悉System.Action类,该类只不过是public delegate void Action ();的定义并且可以避免在不返回参数的情况下定义函数的委托。如有必要,可以使用泛型Action <T, …>添加函数参数,这意味着您可以列出所需数量的具有给定类型的函数参数。

Event

event是委托的附加组件,并且出于安全原因,它直接从类外部阻止委托的设置(允许在事件声明的类内部进行设置),仅提供添加/删除订户的功能。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class EventTest {
    // Event公告
    // Act1ion <string>-在System程序包中声明为public delegate void Action <in T>(T obj);
    // 分配一个空的委托委托人{}将避免在调用事件时额外检查是否为null,因为在没有侦听器的情况下,该调用将引发NullReferenceException
    public event Action<string> print = delegate { };

    public DelegateTest()
    {
        // 添加订户
        print += PrintValue;
        // 添加订户
        print += PrintData;
        // 呼叫所有用户
        p("Event");
    }

    private void PrintData(string s)
    {
        Console.WriteLine("PrintData " + s);
    }

    public void PrintValue(string s)
    {
        Console.WriteLine("PrintValue " + s);
    }
}

执行结果:

1
2
PrintValue Event
PrintData Event

Static event

显而易见,结合使用public static event Action print = delegate {};当您只需要一种机制来提醒订户时,它可以替代单例。

警告

确保删除不必要的订阅,因为这可能会干扰垃圾收集器并导致内存泄漏。

结论

观察者是一种必不可少的模式,它将减少对象的互连性并增加灵活性。与往常一样,它不是免费的,您将不得不牺牲联系和状态的证据。但是,这种灵活性可以提供将项目划分为子模块的能力,这对于大型项目很重要。 下次见!^_^


如果您喜欢这篇文章,可以为它提供支持



Privacy policyCookie policyTerms of service
Tulenber 2020