Паттерн Observer
Часть раздела Объектно-ориентированное программирование путешествия по Python на Coddy. Урок 47 из 64.
Паттерн Observer создаёт отношение «один ко многим», при котором один объект (subject) уведомляет несколько объектов (observers), когда его состояние изменяется.
Вот простой класс 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)Subject хранит список observers и может уведомить их всех одновременно.
Создайте простые классы-наблюдатели:
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. Это полезно для уведомлений, систем событий и поддержания синхронизации между несколькими частями приложения.
Задание
СреднеРеализуйте паттерн Observer, создав систему мониторинга погоды. Вам необходимо создать два класса в обозначенных областях кода.
Шаг 1: Создайте класс WeatherStation
Напишите свой класс WeatherStation там, где указан комментарий. Этот класс должен:
- Наследоваться от класса Subject (используйте
class WeatherStation(Subject):) - Инициализироваться следующим образом:
- Вызовите конструктор родительского класса с помощью
super().__init__() - Установите начальную температуру равной 0, используя атрибут с одним символом подчёркивания
self._temperature(согласно соглашению Python для внутреннего атрибута)
- Вызовите конструктор родительского класса с помощью
- Реализовать
<strong>set_temperature(self, temperature)</strong>:- Обновить атрибут внутренней температуры
- Вызвать
self.notify(self._temperature), чтобы уведомить всех наблюдателей
- Реализовать
<strong>get_temperature(self)</strong>:- Вернуть текущее значение температуры
Шаг 2: Создайте класс WeatherDisplay
Напишите свой класс WeatherDisplay там, где указан комментарий. Этот класс должен:
- Наследоваться от класса Observer (используйте
class WeatherDisplay(Observer):) - Инициализироваться следующим образом:
- Принимать параметр
name - Сохранять имя как
self.name
- Принимать параметр
- Реализовать
<strong>update(self, temperature)</strong>:- Выводить сообщение об обновлении температуры в точно указанном ниже формате
Формат сообщения:
Когда дисплей получает обновление температуры, он должен вывести ровно следующее:
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