{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Паттерн Наблюдатель (Observer)\n", "\n", "Паттерн Наблюдатель является поведенческим паттерном проектирования. Он предназначен для организации взаимодействия между классами. Он реализует взаимодействия типа один-много, при котором множество объектов получают информацию об изменениях основного объекта. \n", "\n", "По данному принципу работает огромное количество приложений. Это могут быть новостные рассылки, уведомления от приложений на смартфонах, автоматическая рассылка почты, системы достижений в израх и многое другое.\n", "\n", "Вместо решения, при котором объект наблюдатель опрашивает наблюдаемый объект о произошедших изменениях, наблюдаймый объект самостоятельно уведомляет о них наблюдателя.\n", "\n", "В паттерне наблюдатель в наблюдаемой системе должен быть имплементирован интерфейс наблюдаемого объекта, позволяющий \"подписывать\" пользователя на обновления объекта и отправлять всем подписанным пользователям уведомления об изменениях. Также должны существовать наблюдатели, реализующие интерфейс наблюдателя. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Структура наблюдателя\n", "<img src=\"https://upload.wikimedia.org/wikipedia/commons/8/8a/Observer_UML.png\">\n", "\n", "Для паттерна Observer необходимы следующие классы:\n", "\n", "* Абстрактный наблюдаемый объект\n", "* Абстрактный наблюдатель\n", "* Конкретный наблюдаемый объект\n", "* Конкретные наблюдатели\n", "\n", "У наблюдаемого объекта должны быть реализованы методы:\n", "\n", "* Подписать наблюдателя на обновления\n", "* Отписать от обновления\n", "* Уведомить всех подписчиков об изменениях\n", "\n", "У наблюдателя должен быть реализован метод update, который будет вызван наблюдаемым объектом при обновлении." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Использование паттерна Наблюдатель\n", "\n", "При использовании паттерна Наблюдатель создаются наблюдатели и система. Для использования паттерна наблюдатель подписывается на обновления системы. При изменениях система оповещает об изменениях всех текущих подписчиков при помощи вызова у подписчиков метода update." ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Реализация паттерна Наблюдатеь" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from abc import ABC, abstractmethod\n", "\n", "class NotificationManager: # Наблюдаемая система\n", " def __init__(self): \n", " self.__subscribers = set() # При инициализации множество подписчиков звдвется пустым\n", " \n", " def subscribe(self, subscriber):\n", " self.__subscribers.add(subscriber) # Для того чтобы подмисать пользователя, он добавляется во множество подписчиков\n", " \n", " def unsubcribe(self, subscriber):\n", " self.__subscribers.remove(subscriber) # Удаление подписчика из списка\n", " \n", " def notify(self, message):\n", " for subscriber in self.__subscribers:\n", " subscriber.update(message) # Отправка уведомления всем подписчикам" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class AbstractObserver(ABC):\n", " @abstractmethod\n", " def update(self, message): # Абстрактный наблюдатель задает метод update \n", " pass\n", "\n", "class MessageNotifier(AbstractObserver):\n", " def __init__(self, name):\n", " self.__name = name\n", " \n", " def update(self, message): # Конкретная реализация метода update\n", " print(f'{self.__name} recieved message!')\n", " \n", "class MessagePrinter(AbstractObserver):\n", " def __init__(self, name):\n", " self.__name = name\n", " \n", " def update(self, message): # Конкретная реализация метода update\n", " print(f'{self.__name} recieved message: {message}')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Printer2 recieved message: Hi!\n", "Printer1 recieved message: Hi!\n", "Notifier1 recieved message!\n" ] } ], "source": [ "notifier1 = MessageNotifier(\"Notifier1\")\n", "printer1 = MessagePrinter(\"Printer1\")\n", "printer2 = MessagePrinter(\"Printer2\")\n", "\n", "manager = NotificationManager()\n", "\n", "manager.subscribe(notifier1)\n", "manager.subscribe(printer1)\n", "manager.subscribe(printer2)\n", "\n", "manager.notify(\"Hi!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.3" } }, "nbformat": 4, "nbformat_minor": 2 }