Паттерн Observer
Часть раздела Объектно-ориентированное программирование путешествия по Python на Coddy. Урок 47 из 64.
Паттерн «Наблюдатель» создаёт отношение «один ко многим», при котором один объект (субъект) уведомляет несколько объектов (наблюдателей), когда его состояние изменяется.
Вот простой класс Subject, который управляет наблюдателями:
class Subject:
def __init__(self):
self._observers = []
def add_observer(self, observer):
self._observers.append(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)Субъект хранит список наблюдателей и может уведомить их всех сразу.
Создайте простые классы наблюдателей:
class EmailNotifier:
def update(self, message):
print(f"Email sent: {message}")
class SMSNotifier:
def update(self, message):
print(f"SMS sent: {message}")У каждого наблюдателя есть метод update, который вызывается при получении уведомления.
Используй шаблон «Наблюдатель»:
# Создать субъект
news = Subject()
# Создать наблюдателей
email = EmailNotifier()
sms = SMSNotifier()
# Добавить наблюдателей к субъекту
news.add_observer(email)
news.add_observer(sms)
# Уведомить всех наблюдателей
news.notify("Breaking news: Python is awesome!")Создайте практический пример с отслеживанием цены акций:
class Stock:
def __init__(self, symbol, price):
self.symbol = symbol
self._price = price
self._observers = []
def add_observer(self, observer):
self._observers.append(observer)
def set_price(self, price):
self._price = price
self.notify()
def notify(self):
for observer in self._observers:
observer.update(self.symbol, self._price)
class Investor:
def __init__(self, name):
self.name = name
def update(self, symbol, price):
print(f"{self.name} notified: {symbol} is now ${price}")
# Используйте трекер акций
apple_stock = Stock("AAPL", 150)
investor1 = Investor("Alice")
investor2 = Investor("Bob")
apple_stock.add_observer(investor1)
apple_stock.add_observer(investor2)
apple_stock.set_price(155) # Уведомляет всех инвесторовВывод:
Email sent: Breaking news: Python is awesome!
SMS sent: Breaking news: Python is awesome!
Alice notified: AAPL is now $155
Bob notified: AAPL is now $155Ключевой момент: шаблон «Наблюдатель» позволяет одному объекту автоматически уведомлять множество других при изменении чего-либо. Субъект поддерживает список наблюдателей и при необходимости вызывает их метод update. Это полезно для уведомлений, систем событий и синхронизации разных частей приложения.
Задание
СреднеРеализуйте шаблон «Наблюдатель», создав систему мониторинга погоды. Вам нужно создать два класса в указанных областях кода.
Шаг 1: Создайте класс WeatherStation
Напишите класс WeatherStation там, где указано в комментарии. Этот класс должен:
- Наследоваться от класса Subject (используйте
class WeatherStation(Subject):) - При инициализации:
- Вызвать конструктор родительского класса с помощью
super().__init__() - Задать начальную температуру 0 с помощью атрибута с одним подчёркиванием
self._temperature(соглашение Python для внутреннего атрибута)
- Вызвать конструктор родительского класса с помощью
- Реализовать
set_temperature(self, temperature):- Обновить внутренний атрибут температуры
- Вызвать
self.notify(self._temperature), чтобы уведомить всех наблюдателей
- Реализовать
get_temperature(self):- Вернуть текущее значение температуры
Шаг 2: Создайте класс WeatherDisplay
Напишите класс WeatherDisplay там, где указано в комментарии. Этот класс должен:
- Наследоваться от класса Observer (используйте
class WeatherDisplay(Observer):) - При инициализации:
- Принять параметр
name - Сохранить имя в
self.name
- Принять параметр
- Реализовать
update(self, temperature):- Вывести сообщение об обновлении температуры в точном формате, указанном ниже
Формат сообщения:
Когда дисплей получает обновление температуры, он должен вывести в точности:
Display [name]: Current temperature is [temperature]CПример использования:
# Create weather station and displays
station = WeatherStation()
phone_display = WeatherDisplay("Phone")
tablet_display = WeatherDisplay("Tablet")
# Attach displays to station
station.attach(phone_display)
station.attach(tablet_display)
# Update temperature - both displays will be notified
station.set_temperature(25.5)
# Output:
# Display Phone: Current temperature is 25.5C
# Display Tablet: Current temperature is 25.5CВажные замечания:
- Методы
attach()иdetach()уже реализованы в базовом классе Subject — вам не нужно реализовывать их или вызывать в классе WeatherStation - В приведённом выше примере использования
station.attach(phone_display)вызывается пользователем вашего класса, а не внутри реализации WeatherStation - Классу WeatherStation достаточно вызвать
self.notify(), когда температура изменится, — базовый класс Subject выполнит остальную работу - Сосредоточьтесь на реализации трёх обязательных методов в WeatherStation и двух обязательных методов в WeatherDisplay, как указано выше
Попробуйте сами
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, data):
for observer in self._observers:
observer.update(data)
class Observer:
def update(self, data):
pass
# Напишите здесь свой класс WeatherStation
# Напишите здесь свой класс WeatherDisplay
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыПараметр selfМетодыАтрибутыМетод-конструктор (__init__)Повторение — Простой калькулятор4Наследование
Базовое наследованиеФункция super()Переопределение методовМножественное наследованиеПорядок разрешения методовИтоги — Иерархия сотрудников7Специальные методы
Введение в магические методыПерегрузка операторовМагические методы контейнеровПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy5Полиморфизм
Снова о переопределении методовУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовИтоги — Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияМиксиныСтатические методы и методы классаДекораторы классовМенеджеры контекста11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Свойства классов
Переменные экземпляра и классаДекораторы свойствПриватные атрибутыИтоги — Менеджер банковского счета6Инкапсуляция
Public, Protected, Private члены классаМодификаторы доступаСокрытие данныхДекораторы property: продвинутый уровеньИтоги: Система учета студентов12Проект: Управление библиотекой
Обзор проектаКлассы Book и UserСистема выдачи книгФункционал поискаИнтерфейс администратораТестирование и интеграцияПотренируйтесь самостоятельно: Онлайн-компилятор Python