Menu
Coddy logo textTech

תבנית 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)

הנושא שומר רשימה של משקיפים ויכול להודיע לכולם בבת אחת.

צרו מחלקות Observer פשוטות:

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 מאפשרת לאובייקט אחד להודיע אוטומטית לאובייקטים רבים אחרים כשמשהו משתנה. הנושא מנהל רשימה של צופים וקורא למתודת update שלהם בעת הצורך. הדבר שימושי להתראות, למערכות אירועים ולשמירה על סנכרון בין חלקים שונים של היישום.

challenge icon

אתגר

בינוני

ממשו את תבנית 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

quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Python אונליין