繁体   English   中英

C# 对委托、发布者和订阅者感到困惑

[英]C# confused about delegates, publishers and subscribers

考虑以下控制台程序。 它有四个类:Program、Attacker、Defender 和 Helper。 我想从 Defender 类中删除逻辑并使用委托来调用助手。 我在这方面花了一些时间,但不太明白。

我在哪里声明我的代表:在 Program 中还是在 Defender 中? 我在哪里实例化我的委托:在程序中还是在 Defender 中? 我在哪里订阅我的委托:在程序中还是在助手中?

我可以发布我的尝试,但它不会有帮助。

using System;

namespace Delegates19
{
    public class Program
    {
        static void Main(string[] args)
        {
            Attacker a = new Attacker();
            string weapon = "sword";
            a.Attack(weapon);

            Defender d = new Defender();
            d.Help(weapon);

            weapon = "spear";
            a.Attack(weapon);
            d.Help(weapon);
        }
    }
    public class Attacker
    {
        public void Attack(string s)
        {
            Console.WriteLine($"Attacker attacks with {s}");
        }
    }
    public class Defender
    {
        public void Help(string s)
        {
            Console.WriteLine($"Defender is attacked with {s} and calls for help");
            if (s == "sword")
                Helper.Knight();
            if (s == "spear")
                Helper.Bowman();
        }
    }
    public class Helper
    {
        public static void Knight()
        {
            Console.WriteLine($"Knight charges Attacker");
        }
        public static void Bowman()
        {
            Console.WriteLine($"Bowman shoots Attacker");
        }
    }
}

我真的不确定您为什么要这样做,但是这些都有效并且可能会给您一些想法。

除非我了解您对事件/委托的需求,否则我实际上更喜欢您的代码而不是这些。

代表:

public class Defender
{
    private static Action SwordAction = Helper.Knight;
    private static Action SpearAction = Helper.Bowman;

    public void Help(string s)
    {
        Console.WriteLine($"Defender is attacked with {s} and calls for help");
        if (s == "sword")
            SwordAction();
        if (s == "spear")
            SpearAction();
    }
}

public static class Helper
{
    public static void Knight()
    {
        Console.WriteLine($"Knight charges Attacker");
    }

    public static void Bowman()
    {
        Console.WriteLine($"Bowman shoots Attacker");
    }
}

事件:

static void Main(string[] args)
{
    using (var d = new Defender())
    {
        d.GetHelp += StandardDefenseHelp.Defender_GetHelp;
        d.Help("sword");
        d.Help("spear");
    }
}

public class Defender : IDisposable
{
    public event EventHandler<string> GetHelp;

    private void RaiseGetHelp(string weapon) => GetHelp?.Invoke(this, weapon);

    public void Help(string weapon)
    {
        Console.WriteLine($"Defender is attacked with {weapon} and calls for help");
        RaiseGetHelp(weapon);
    }

    public void Dispose()
    {
        GetHelp = null;
    }
}

public static class StandardDefenseHelp
{
    public static void Defender_GetHelp(object sender, string weapon)
    {
        if (weapon == "sword")
            Knight();
        if (weapon == "spear")
            Bowman();
    }

    private static void Knight()
    {
        Console.WriteLine($"Knight charges Attacker");
    }

    private static void Bowman()
    {
        Console.WriteLine($"Bowman shoots Attacker");
    }
}

重要:事件通常是内存泄漏的原因,这就是为什么 Defender 现在是一次性的。

如果您有多个“DefenseHelp”类型,则上述设计可能很有用,并且当防御者需要帮助而防御者本身一无所知时,也应该发生其他事情。

但我只会这样做,如果它带来了一些好处。 我相信 KISS 开发方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM