C # Внедрить наблюдаемый шаблон - PullRequest
0 голосов
/ 28 апреля 2019

Я пытаюсь реализовать наблюдаемый шаблон, используя C #. В моем примере кода у меня есть два вида солдатских лучников двух классов: Лучник и Мечник они реализуют Солдат интерфейс. Солдат интерфейс имеет четыре метода:

  • Attack () - приказывает солдату атаковать врага
  • Died () - этот метод в данном примере не имеет значения
  • Kill () - прикажи нашему солдату убить врага
  • BattleCry () - празднование ВСЕХ моих солдат после того, как убили врага

и одно свойство bool IsEnemyKilled - когда вызывается метод Kill (), IsEnemyKilled становится истинным.

И вот что я хочу сделать: Я знаю, что для реализации шаблона наблюдателя мне нужны поставщик и наблюдатели. Когда один из солдат, например лучник - убивает врага 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();
    }
}

Ответы [ 2 ]

2 голосов
/ 28 апреля 2019

Предлагаю добавить подписчиков (наблюдателей) в ваш повидер (лучник).Таким образом, ваш лучник будет иметь солдат, подписанных на атаки лучника.

Лат разбивает его.

Ваш лучник должен иметь своих наблюдателей:

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();
        ...

Вы можете (и должны) добавить метод оповещения в свой класс солдат, чтобы вы могли вместо этого вызывать егометода BattleCry.

Я считаю следующую статью хорошим примером: https://exceptionnotfound.net/the-daily-design-pattern-observer/

2 голосов
/ 28 апреля 2019

Вам необходимо прикрепить Субъекта (какой-то солдат) к наблюдателю (какой-то другой солдат).
Для этого я сначала добавил три новых члена в Интерфейс Солдата:

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

Реализация Attach и Detach выглядит следующим образом:

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

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

Так как я вижу много повторений, когда вам нужнореализовать это для обоих солдат, рассмотрите возможность изменения Soldier с interface на abstract class.

Когда вы все это сделаете, вам нужно будет соединить (всех) солдат вместе (конечно, в соответствии с желаемой игровой логикой).
Один из способов отслеживания всех солдат будетstatic List<Soldier> в (ваш теперь абстрактный класс) Soldier, где каждый солдат добавляет себя, когда-то созданный.Но вы можете делать все, что захотите.

Это всего лишь некоторые идеи, а не полноценный образец наблюдателя.Так как вы попросили идеи, я хотел бы добавить некоторые из них.Надеюсь, это приведет вас на правильный путь.

Еще один совет: если вам нужно только свойство IsEnemyKilled для уведомления других, вы можете просто пропустить его и вызвать событие EnemyKilled напрямую вместо установки IsEnemyKilled в true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...