C#实现可观察模式

问题描述 投票:0回答:2

我试图用C#实现可观察的模式。在我的示例代码中,我有两种类型的士兵弓箭手两类:弓箭手和剑客他们实施士兵界面。士兵界面有四种方法:

  • 攻击() - 命令士兵攻击敌人
  • Died() - 这个方法在这个例子中并不重要
  • 杀死() - 命令我们的士兵杀死敌人
  • BattleCry() - 庆祝所有我的士兵在阵营被杀之后

和一个属性bool IsEnemyKilled - 当Kill()方法被调用时,IsEnemyKilled变为true。

这就是我想要做的事情:我知道要实现Observer模式我需要Provider和Observers。当一个士兵,例如弓箭手 - 杀死敌人archer.Kill();IsEnemyKilled成为真(这是我的提供者)和我所有其他士兵(我的观察员),例如必须通知剑客和另一名弓箭手IsEnemyKilled是真的,他们必须打电话给BattleCry()。

我很困惑怎么做。如果有人提出想法,我将不胜感激。这是我的示例代码。

namespace ImplementObservable
{
    class Program
    {
        static void Main(string[] args)
        {

            var archer = new Archer();
            var swordsman = new Swordsman();
            archer.Attack();
            archer.Kill();
            Console.ReadKey();
        }
    }

    public class Archer : Soldier
    {
        bool IsEnemyKilled;
        // watch somehow prop "IsEnemyKilled" and if it changes to true call BattleCry() for all units

        public void Attack()
        {
            IsEnemyKilled = false;
            Console.WriteLine("Archer attack!");
        }

        public void Died()
        {
            IsEnemyKilled = false;
            Console.WriteLine("Archer died :(");
        }

        public void Kill()
        {
            IsEnemyKilled = true;
            Console.WriteLine("Archer killed enemy! Hurray!!");
        }

        public void BattleCry()
        {
            Console.WriteLine("Archer: Go for victory !");
        }
    }

    public class Swordsman : Soldier
    {
        bool IsEnemyKilled;
        // watch somehow prop "IsEnemyKilled" and if it changes to true call BattleCry() for all units

        public void Attack()
        {
            IsEnemyKilled = false;
            Console.WriteLine("Swordsman attack!");
        }

        public void Died()
        {
            IsEnemyKilled = false;
            Console.WriteLine("Swordsman died :(");
        }
        public void Kill()
        {
            IsEnemyKilled = true;
            Console.WriteLine("Swordsman killed enemy! Hurray!!");
        }

        public void BattleCry()
        {
            Console.WriteLine("Swordsman: Go for victory !");
        }
    }

    public interface Soldier
    {
        void Kill();

        void Attack();

        void Died();

        void BattleCry();
    }
}
c# design-patterns observer-pattern observers
2个回答
2
投票

你需要将主体(一些士兵)附加到观察者(一些其他士兵)。 为实现这一目标,我首先在Soldier-Interface中添加了三个新成员:

event Action EnemyKilled;
void Attach(Soldier observer);
void Detach(Soldier observer);

这里的事件是通知主题并使用财产的设定者解雇它。我更改了属性如下:

private bool isEnemyKilled;

private bool IsEnemyKilled {
    get => isEnemyKilled;
    set {
        isEnemyKilled = value;
        if(isEnemyKilled) EnemyKilled?.Invoke();
    }
}

AttachDetach的实施如下:

public void Attach(Soldier observer)
{
    observer.EnemyKilled += BattleCry;
}

public void Detach(Soldier observer)
{
    observer.EnemyKilled -= BattleCry;
}

因为当你必须为两个士兵实现这个时,我看到了很多重复,考虑将Soldierinterface改为abstract class

完成所有这些后,您需要将(全部)士兵连接在一起(当然根据您所需的游戏逻辑)。 跟踪所有士兵的一种方法是(自己现在的抽象类)static List<Soldier>中的Soldier,每个士兵在创建后自我添加。但你可以做任何你想做的事情。

这些只是一些想法,并不是一个完整的观察者模式。既然你问了我想要的想法。希望它能带你走上正轨。

另一个提示:如果你只需要属性IsEnemyKilled来通知其他人,你可以简单地把它留下来直接调用事件EnemyKilled而不是将IsEnemyKilled设置为true


2
投票

我建议你的订阅者(观察员)加入订阅者(观察者)。这样,你的射手将有士兵订阅射手的攻击。

拉特打破了它。

你的弓箭手应该有他的观察员:

public class Archer : Soldier
    {
        bool IsEnemyKilled;
        private List<Soldirer> soldiers = new List<Soldier>();

        public void Attack()
...

现在让我们通知胜利:

    public void Attack()
    {
        IsEnemyKilled = false;
        Console.WriteLine("Archer attack!");

        soldiers.foreach(soldier => soldier.BattleCry());
    }

最后,让我们订阅我们的士兵:

public class Archer : Soldier {
...
    public void subscribe(Soldier) {
            soldiers.add(soldier);
    }
}

static void Main(string[] args)
        {

            var archer = new Archer();
            var swordsman = new Swordsman();
        ...

您可以(并且应该)向Soldier类添加警报方法,这样您就可以调用它而不是BattleCry方法。

我发现以下文章是一个很好的例子:https://exceptionnotfound.net/the-daily-design-pattern-observer/

© www.soinside.com 2019 - 2024. All rights reserved.