简体   繁体   中英

C# confused about delegates, publishers and subscribers

Consider the following console program. It has four classes: Program, Attacker, Defender, and Helper. I want to remove the logic from the Defender class and use delegates to call helpers. I've spent some time on this and can't quite get it.

Where do I declare my delegate: in Program or in Defender? Where do I instantiate my delegate: in Program or in Defender? Where do I subscribe my delegate: in Program or in Helper?

I could post my attempts but it wouldn't be helpful.

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");
        }
    }
}

I'm really not sure why you would want to do this, but these both work and might give you ideas.

Unless I understand your need for events/delegates I actually prefer your code over these.

Delegates:

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");
    }
}

Events:

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");
    }
}

Important: events often are the cause of memory leaks, that's why Defender is now disposable.

The above design could be useful if you have multiple "DefenseHelp" types and other things also should happen when a defender needs help that the defender itself needs to know nothing about.

But I'd only do this if it gave some benefit. I believe in the KISS development methodology.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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