Menu
Coddy logo textTech

Паттерн Observer

Часть раздела Object Oriented Programming путешествия по Python на Coddy — урок 47 из 64.

Паттерн «Наблюдатель» (Observer Pattern) создает связь «один ко многим», при которой один объект (субъект) уведомляет множество других объектов (наблюдателей) об изменении своего состояния.

Вот простой класс 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

Ключевой момент: Паттерн «Наблюдатель» (Observer Pattern) позволяет одному объекту автоматически уведомлять множество других при изменении своего состояния. Субъект хранит список наблюдателей и вызывает их метод update, когда это необходимо. Это полезно для систем уведомлений, обработки событий и синхронизации различных частей приложения.

challenge icon

Задание

Средне

Реализуйте паттерн «Наблюдатель» (Observer Pattern), создав систему мониторинга погоды. Вам необходимо создать два класса в специально отведенных местах кода.

Шаг 1: Создайте класс WeatherStation

Напишите класс WeatherStation там, где указано в комментарии. Этот класс должен:

  • Наследоваться от класса Subject (используйте class WeatherStation(Subject):)
  • Инициализироваться следующим образом:
    • Вызвать конструктор родительского класса с помощью super().__init__()
    • Установить начальную температуру равной 0, используя приватный атрибут self._temperature
  • Реализовать метод <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, как указано выше.

Шпаргалка

Паттерн «Наблюдатель» (Observer Pattern) создает связь «один ко многим», при которой один объект (субъект) уведомляет несколько объектов (наблюдателей) об изменении своего состояния.

Базовый класс 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)

Классы наблюдателей с методом update:

class EmailNotifier:
    def update(self, message):
        print(f"Email sent: {message}")

class SMSNotifier:
    def update(self, message):
        print(f"SMS sent: {message}")

Использование паттерна «Наблюдатель»:

# Создание субъекта
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}")

Паттерн «Наблюдатель» позволяет одному объекту автоматически уведомлять множество других при возникновении изменений. Субъект хранит список наблюдателей и вызывает их метод update при необходимости.

Попробуйте сами

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

quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Object Oriented Programming