30 листопада 2010 р.

Запізнілий "Патерн Вівторка" #17: Спостерігач (Observer)

Багато людей люблять дивитися бокс. Але крім того, що люди його дивляться хтось то все діло фінансує. Левова частка тих фінансів приходить від всяких фанів і азартних гравців, які програють купу грошей ставлячи ставки.


Уявімо що ми маємо боксерську гру і є двоє людей що ставлять ставки – один любить ризиковані ставки, а інши навпаки дуже консервативний, і завжди  кладе на того, хто швидше за все виграє бій. Хто такі ці гравці?


СПОСТЕРІГАЧ


Як і не було важко здогадатися гравці – це спостерігачі (Observer), а бійка, на яку вони ставлять гроші є суб’єкт (subject). Вони постійно спостерігають за ходом бійки, щоб змінити свої ставки.

Спостерігач – це дизайн патерн, що дозволяє автоматично реагувати багатьом об’єктам на зміну стану певного іншого об’єкту.

Отже кожен поважаючий себе азартний гравець може оновити свої ставки коли треба буде, тому він має метод Update().

public interface IObserver
    {
        void Update(ISubject subject);
    }

    public class RiskyPlayer : IObserver
    {
        public string BoxerToPutMoneyOn { get; set; }

        public void Update(ISubject subject)
        {
            var boxFight = (BoxFight)subject;

            BoxerToPutMoneyOn = (boxFight.BoxerAScore > boxFight.BoxerBScore) ? "I put on boxer B, if he win I get more!" : "I put on boxer A, if he win I get more!";


            Console.WriteLine("RISKYPLAYER:{0}", BoxerToPutMoneyOn);
        }
    }

    public class ConservativePlayer : IObserver
    {
        public string BoxerToPutMoneyOn { get; set; }

        public void Update(ISubject subject)
        {
            var boxFight = (BoxFight)subject;

            BoxerToPutMoneyOn = (boxFight.BoxerAScore < boxFight.BoxerBScore) ? "I put on boxer B, better be safe!" : "I put on boxer A, better be safe!";

            Console.WriteLine("CONSERVATIVEPLAYER:{0}", BoxerToPutMoneyOn);
        }
    }

Ось сама гра, яку споглядають наші гравці:

public interface ISubject
    {
        void AttachObserver(IObserver observer);
        void DetachObserver(IObserver observer);
        void Notify();
    }

    public class BoxFight : ISubject
    {
        public List<IObserver> Observers { get; private set; }
        public int RoundNumber { get; private set; }

        private Random Random = new Random();

        public int BoxerAScore { get; set; }
        public int BoxerBScore { get; set; }

        public BoxFight()
        {
            Observers = new List<IObserver>();
        }

        public void AttachObserver(IObserver observer)
        {
            Observers.Add(observer);
        }

        public void DetachObserver(IObserver observer)
        {
            Observers.Remove(observer);
        }

        public void NextRound()
        {
            RoundNumber++;

            BoxerAScore += Random.Next(0, 5);
            BoxerBScore += Random.Next(0, 5);

            Notify();
        }

        public void Notify()
        {
            foreach (var observer in Observers)
            {
                observer.Update(this);
            }
        }
    }

Використання:

var boxFight = new BoxFight();

            var riskyPlayer = new RiskyPlayer();
            var conservativePlayer = new ConservativePlayer();

            boxFight.AttachObserver(riskyPlayer);
            boxFight.AttachObserver(conservativePlayer);


            boxFight.NextRound();
            boxFight.NextRound();
            boxFight.NextRound();
            boxFight.NextRound();

А ось її вивід:

RISKYPLAYER:I put on boxer A, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer A, better be safe!

RISKYPLAYER:I put on boxer B, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer A, better be safe!

RISKYPLAYER:I put on boxer B, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer A, better be safe!

RISKYPLAYER:I put on boxer B, if he win I get more!
CONSERVATIVEPLAYER:I put on boxer A, better be safe!

Було дуже коротко і лаконічно. Бо це дуже запізнілий патерн вівторка – майже середи.


Моя табличка Патернів
Developer's RoadMap To Success

3 коментарі:

  1. Як завжди цікавий приклад. Було б непогано доповнити статтю інформацією про Obsarvable Collection, IObserver, IObservable - тим що вже присутнє у .Net-і.

    ВідповістиВидалити
  2. Дуже дякую за коментар. Я думаю що всякі такі речі як ObservableCollection і інше вже вбудоване у можу можна буде подописувати у книгу, але просто вагаюся чи то не буде зайвим.

    ВідповістиВидалити
  3. Все залежить на кого орієнтована книга, якщо виключно на .NET розробників то було б непогано мати інформацію про готові реалізації патернів, але якщо для більшого загалу - то ця інформація може виявитись зайвою.

    ВідповістиВидалити