Mẫu Observer
Thuộc phần Lập trình hướng đối tượng trong hành trình Python của Coddy. Bài học 47 trên 64.
Mẫu Observer tạo ra mối quan hệ một với nhiều, trong đó một đối tượng (chủ thể) thông báo cho nhiều đối tượng (bên quan sát) khi trạng thái của nó thay đổi.
Đây là một lớp Subject đơn giản quản lý các observer:
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)Đối tượng lưu danh sách các trình quan sát và có thể thông báo cho tất cả cùng lúc.
Tạo các lớp quan sát đơn giản:
class EmailNotifier:
def update(self, message):
print(f"Email sent: {message}")
class SMSNotifier:
def update(self, message):
print(f"SMS sent: {message}")Mỗi observer có một phương thức update được gọi khi nhận thông báo.
Sử dụng mẫu observer:
# Tạo đối tượng chủ thể
news = Subject()
# Tạo các đối tượng quan sát
email = EmailNotifier()
sms = SMSNotifier()
# Thêm các đối tượng quan sát vào chủ thể
news.add_observer(email)
news.add_observer(sms)
# Thông báo cho tất cả đối tượng quan sát
news.notify("Breaking news: Python is awesome!")Tạo một ví dụ thực tế về trình theo dõi giá cổ phiếu:
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}")
# Sử dụng công cụ theo dõi cổ phiếu
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) # Thông báo cho tất cả nhà đầu tưĐầu ra:
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Điểm chính: Mẫu Observer cho phép một đối tượng tự động thông báo cho nhiều đối tượng khác khi có thay đổi. Đối tượng chủ thể duy trì danh sách các đối tượng quan sát và gọi phương thức update của chúng khi cần. Mẫu này hữu ích cho thông báo, hệ thống sự kiện và giúp nhiều phần trong ứng dụng của bạn luôn đồng bộ.
Thử thách
Trung bìnhTriển khai Observer Pattern bằng cách tạo một hệ thống theo dõi thời tiết. Bạn cần tạo hai lớp ở những vị trí được chỉ định trong code.
Bước 1: Tạo lớp WeatherStation
Viết lớp WeatherStation tại vị trí được ghi chú. Lớp này cần:
- Kế thừa từ lớp Subject (dùng
class WeatherStation(Subject):) - Khởi tạo với:
- Gọi hàm khởi tạo của lớp cha bằng
super().__init__() - Đặt nhiệt độ ban đầu là 0 bằng thuộc tính có một dấu gạch dưới
self._temperature(quy ước của Python cho thuộc tính nội bộ)
- Gọi hàm khởi tạo của lớp cha bằng
- Triển khai
set_temperature(self, temperature):- Cập nhật thuộc tính nhiệt độ nội bộ
- Gọi
self.notify(self._temperature)để thông báo cho tất cả observer
- Triển khai
get_temperature(self):- Trả về giá trị nhiệt độ hiện tại
Bước 2: Tạo lớp WeatherDisplay
Viết lớp WeatherDisplay tại vị trí được ghi chú. Lớp này cần:
- Kế thừa từ lớp Observer (dùng
class WeatherDisplay(Observer):) - Khởi tạo với:
- Nhận một tham số
name - Lưu tên vào
self.name
- Nhận một tham số
- Triển khai
update(self, temperature):- In thông báo cập nhật nhiệt độ theo chính xác định dạng bên dưới
Định dạng thông báo:
Khi màn hình nhận được thông tin cập nhật nhiệt độ, màn hình phải in chính xác:
Display [name]: Current temperature is [temperature]CVí dụ sử dụng:
# 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.5CLưu ý quan trọng:
- Các phương thức
attach()vàdetach()đã được triển khai trong lớp cơ sở Subject, bạn không cần triển khai chúng hoặc gọi chúng trong lớp WeatherStation - Trong ví dụ sử dụng ở trên, người dùng lớp của bạn gọi
station.attach(phone_display), không phải bên trong phần triển khai WeatherStation - WeatherStation chỉ cần gọi
self.notify()khi nhiệt độ thay đổi, lớp cơ sở Subject sẽ xử lý phần còn lại - Tập trung triển khai ba phương thức bắt buộc trong WeatherStation và hai phương thức bắt buộc trong WeatherDisplay như mô tả ở trên
Tự làm thử
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
# Viết lớp WeatherStation ở đây
# Viết lớp WeatherDisplay ở đây
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTham số selfPhương thứcThuộc tínhPhương thức khởi tạo (__init__)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnHàm super()Ghi đè phương thứcKế thừa đa lớpThứ tự phân giải phương thứcÔn tập: hệ thống phân cấp nhân viên2Decorator
Giới thiệu về decoratorDecorator thuộc tínhDecorator phương thức tĩnhDecorator phương thức lớp5Tính đa hình
Xem lại cách ghi đè phương thứcKiểu gõ vịtLớp và phương thức trừu tượngThiết kế giao diệnÔn tập: máy tính hình học8Các khái niệm OOP nâng cao
Kết hợp và kế thừaMixinPhương thức tĩnh và phương thức lớpDecorator lớpTrình quản lý ngữ cảnhTự luyện tập: Trình biên dịch Python online