Паттерны Проектирования. Наблюдатель



    Паттерны Проектирования. Наблюдатель

    Всем известно, как работает подписка на газету:

    1. Издатель открывает свое дело и начинает выпускать газету

    2. Вы оформляете подписку у определенного издателя, и каждый раз когда выходит новый выпуск - вы получаете газету, пока не окончиться срок подписки.

    3. Если вы более не хотите получать газету - вы прекращаете подписку.

    4. Пока газета продолжает публиковаться - новые люди могут подписаться на нее, либо те кто подписан - отписаться.

    Как в жизни - так и в программировании, только в данном случае Издатель называеться Субъектом, а Подписчики - Наблюдателями.

    Определение:

    Паттерн Наблюдатель определяет отношение один-ко-многим между объектами таким образом, что при изменении состояния одного объекта, происходит автоматическое оповещение и обновление всех зависимых объектов.

    Далее покажем пример реализации на языке C#.

    1. Создадим интерфейс субъекта:

    interface IObserver
        {
            void Update();
        }

    2. Создадим интерфейс для наблюдателей:

    interface IObservable
        {
            void RegisterObserver(IObserver o);
            void RemoveObserver(IObserver o);
            void NotifyObservers();
        }

    3. Создадим класс субъекта, , реализующий интерфейс IObservable:

    class Times : IObservable
        {
            
            List<IObserver> observers;
            public Times()
            {
                observers = new List<IObserver>();
            }
            public void RegisterObserver(IObserver o)
            {
                observers.Add(o);
            }

            public void RemoveObserver(IObserver o)
            {
                observers.Remove(o);
            }

            public void NotifyObservers()
            {
                foreach (IObserver o in observers)
                {
                    o.Update();
                }
            }

            public void NewTimes()
            {
                NotifyObservers();
            }
        }

    4. Создадим класс подписчиков, реализующий интерфейс IObserver:

    class Subscriber : IObserver
        {
            public string Name { get; set; }
            IObservable times;
            public Subscriber(string name, IObservable obs)
            {
                this.Name = name;
                times = obs;
                times.RegisterObserver(this);
            }
            public void Update()
            {
                Console.WriteLine("Подписчик {0} получил новый выпуск", this.Name);
                
            }
            public void Unsubscribe()
            {
                times.RemoveObserver(this);
                times = null;
            }
        }

    5. Код программы:

    static void Main(string[] args)
            {
                Times times = new Times();
                Subscriber subscriber1 = new Subscriber("Станислав Михайлович", times);
                Subscriber subscriber2 = new Subscriber("Иван Иваныч", times);
                Subscriber subscriber3 = new Subscriber("Василий Петрович", times);
                // новый выпуск газеты
                times.NewTimes();

                Console.WriteLine("------------------------------------------------------");
                
                // подписчик1 отписался от подписки
                subscriber1.Unsubscribe();

                // новый выпуск газеты
                times.NewTimes();

                Console.Read();
            }