Паттерны проектирования: Наблюдатель(Observer)

Наблюдатель(Observer) – это поведенческий проектирования. Он определяет зависимость типа «один ко многим» таким образом, что при изменении объекта, все зависящие от его получают сообщение об этом событии.
Задача: Задачей данного паттерна является выбор подходящего алгоритма, на основе обрабатываемых данных или типу клиента.
Простейшая схема работы паттерна:

Данный шаблон стоит применять в тех случаях, когда существует как минимум один объект, рассылающий сообщения, имеется не менее одного получателя сообщения и количество получателей может меняться в процессе работы приложения. Шаблон часто применяется в тех случаях, когда отправителя не интересует, что получатели сделают с полученными данными.
 Рассмотрим следующую проблему: есть сервис, который поддерживает несколько платформ (Windows Phone, Android), необходимо реализовать PUSH уведомления на все подписанные устройства.

Создадим класс Messages:

 
public delegate void MessagesContentChangeEventHandler(object sender, String message);

    public class Messages
    {
        public event MessagesContentChangeEventHandler ContentChanged;

        private readonly Random _rand;

        public Messages()
        {
            _rand = new Random();
        }

        private String GetMessage()
        {
            var messages = new string[] {"Сообщение первое", "Тестирование Push уведомлений", "Срочная новость", "Оповещение!!!"};
            return messages[_rand.Next(messages.Count())];
        }


        public void MessageAvailable()
        {
            var message = GetMessage();
          
            if (ContentChanged != null)
            {
                ContentChanged(this, message);
            }
        }
    }

Здесь стоит обратить внимание на событие ContentChanged, именно на это событие будут подписываться телефоны, для получения Push уведомления. А получать они его будут, когда будет вызван метод MessageAvailable. В нем случайным образом получается следующее сообщение для рассылки, затем, если есть подписчик, то вызывается событие ContentChanged.

Теперь напишем интерфейс IObserver.

 
    interface IObserver
    {
        void Display();
        void Update(object sender, String message);
    }

Возможно это не самый оптимальный тип интерфейса, но для данной задачи вполне хватит и такого. Теперь создадим класс для оповещения Windows Phone девайса.

 
    class WindowsPhone:IObserver
    {
        private String _name;
        private String _message;

        public WindowsPhone(String name)
        {
            _name = name;
        }

        public void Display()
        {
            Console.WriteLine("WP device {0}. Message is received: {1}", _name,_message );
        }

        public void Update(object sender, String message)
        {
            _message = message;
            Display();
        }
    }

Как можно увидеть, метод Update подходит для подписки на событие ContentChanged.При его вызове, пере запишется текущее сообщение и вызовется метод Display(); Который выведет его на экран. Класс для Android устройств будет аналогичным:

 
   class AndroidPhone:IObserver
    {
        private readonly String _name;
        private String _message;

        public AndroidPhone(string name)
        {
            _name = name;
        }

        public void Display()
        {
            Console.WriteLine("Android device {0}.  Message is received: {1}", _name, _message);
        }

        public void Update(object sender, string message)
        {
            _message = message;
            Display();
        }
    } 

Теперь осталось протестировать написанный код:

 
            var wp1 = new WindowsPhone("Lumia 620");
            var wp2 = new WindowsPhone("Lumia 1020");
            var wp3 = new WindowsPhone("Lumia 930");

            var android1 = new AndroidPhone("Nexus 4");
            var android2 = new AndroidPhone("Nexus 5");
            var android3 = new AndroidPhone("Galaxy 3");

            var observer = new Messages();

            //Подписываем на уведомления Windows Phone девайсы
            observer.ContentChanged += wp1.Update;
            observer.ContentChanged += wp2.Update;
            observer.ContentChanged += wp3.Update;

            //Подписываем на уведомления Android девайсы
            observer.ContentChanged += android1.Update;
            observer.ContentChanged += android2.Update;
            observer.ContentChanged += android3.Update;

            
            //Первое PUSH уведомление
            observer.MessageAvailable();

            //Удаляем из рассылки Lumia 620 и Nexus 4
            observer.ContentChanged -= wp1.Update;
            observer.ContentChanged -= android1.Update;

            Console.WriteLine("\n---Были удалены некоторые девайсы из рассылки---");

            //Второе PUSH уведомление
            observer.MessageAvailable();
            Console.WriteLine("\n---Третья рассылка---");
            //Третья рассылка
            observer.MessageAvailable();

Результат выполнения:

Исходный код учебного проекта: https://github.com/flash2048/Patterns/tree/master/Observer

Добавить комментарий