Menu
Coddy logo textTech

תבנית Observer

חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 73 מתוך 91.

תבנית Observer היא תבנית עיצוב התנהגותית שיוצרת קשר של אחד לרבים בין אובייקטים. כאשר אובייקט אחד (הנושא) משנה את מצבו, כל התלויים בו (המשקיפים) מקבלים הודעה ומתעדכנים באופן אוטומטי.

חשבו על הרשמה לניוזלטר. הניוזלטר הוא הנושא, והמנויים הם צופים. כשמתפרסמת מהדורה חדשה, כל המנויים מקבלים אותה באופן אוטומטי, בלי שהניוזלטר יצטרך לדעת את הפרטים של כל מנוי.

הנה מימוש בסיסי ב-PHP:

<?php
interface Observer {
    public function update(string $message): void;
}

class Newsletter {
    private array $subscribers = [];
    
    public function subscribe(Observer $observer): void {
        $this->subscribers[] = $observer;
    }
    
    public function publish(string $content): void {
        foreach ($this->subscribers as $subscriber) {
            $subscriber->update($content);
        }
    }
}

class EmailSubscriber implements Observer {
    public function __construct(private string $email) {}
    
    public function update(string $message): void {
        echo "Sending to {$this->email}: $message\n";
    }
}

$newsletter = new Newsletter();
$newsletter->subscribe(new EmailSubscriber("alice@example.com"));
$newsletter->subscribe(new EmailSubscriber("bob@example.com"));
$newsletter->publish("New article released!");

פלט:

Sending to alice@example.com: New article released!
Sending to bob@example.com: New article released!

התבנית מנתקת את הנושא מהצופים בו. המחלקה Newsletter לא צריכה לדעת אם היא מודיעה למנויים בדוא״ל, למנויי SMS או לשירותי הודעות דחיפה. היא פשוט קוראת ל־update() בכל רכיב שמממש את הממשק Observer. כך אפשר להוסיף סוגים חדשים של צופים בקלות, בלי לשנות את הקוד הקיים.

challenge icon

אתגר

קל

בואו נבנה מערכת התראות על מחירי מניות באמצעות דפוס Observer. כאשר מחיר של מניה משתנה, יש להודיע אוטומטית לכל המשקיעים הרשומים: זהו יישום מושלם של הדפוס בעולם האמיתי.

תארגן את הקוד שלך בארבעה קבצים:

  • Observer.php: הגדר ממשק Observer עם מתודה אחת, update(string $stockName, float $price): void. זהו החוזה שעל כל הצופים לקיים כדי לקבל התראות.
  • Investors.php: כלול את קובץ Observer וצור שתי מחלקות שמממשות את הממשק:
    • EmailInvestor: מקבלת כתובת אימייל בבנאי שלה (השתמש בקידום פרמטרים בבנאי). המתודה update() שלה מדפיסה "Email to [email]: [stockName] is now $[price]"
    • SmsInvestor: מקבלת מספר טלפון בבנאי שלה. המתודה update() שלה מדפיסה "SMS to [phone]: [stockName] is now $[price]"
  • Stock.php: כלול את קובץ Observer וצור מחלקה Stock שפועלת כנושא. המניה שלך צריכה:
    • לשמור את שם המניה ואת המחיר הנוכחי (השתמש בקידום פרמטרים בבנאי עבור השם, ואתחל את המחיר ל-0.0)
    • לנהל מערך פרטי של צופים
    • לכלול מתודה subscribe(Observer $observer): void להוספת צופים
    • לכלול מתודה setPrice(float $price): void שמעדכנת את המחיר ומודיעה לכל הצופים
    בעת ההודעה לצופים, קרא למתודה update() של כל צופה עם שם המניה והמחיר החדש.
  • main.php: כלול את הקבצים Investors ו-Stock. תקבל שלוש קלטים: שם מניה, כתובת אימייל ומספר טלפון.

    צור Stock עם השם שהתקבל. רשום EmailInvestor עם כתובת האימייל ו-SmsInvestor עם מספר הטלפון.

    הגדר את מחיר המניה ל-150.50 כדי להפעיל התראות לכל המנויים.

דפוס Observer שומר על מחלקת Stock מנותקת משיטות ההתראה הספציפיות. אפשר להוסיף בקלות PushInvestor או SlackInvestor בהמשך, בלי לשנות כלל את מחלקת Stock.

נסו בעצמכם

<?php
require_once 'Investors.php';
require_once 'Stock.php';

// קראו את הקלטים
$stockName = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$phone = trim(fgets(STDIN));

// TODO: צרו Stock עם השם הנתון

// TODO: רשמו EmailInvestor כמנוי באמצעות כתובת האימייל

// TODO: רשמו SmsInvestor כמנוי באמצעות מספר הטלפון

// TODO: הגדירו את מחיר המניה ל-150.50 כדי להפעיל התראות
?>
quiz iconבחנו את עצמכם

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

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

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