תבנית הצופה (אירועים)
חלק מהיחידה תכנות מונחה עצמים במסלול ה-C# של Coddy. שיעור 54 מתוך 70.
תבנית הצופה מגדירה קשר של אחד לרבים, שבו אובייקט אחד (הנושא) מודיע למספר אובייקטים תלויים (צופים) כאשר מצבו משתנה. ב־C#, אירועים מספקים דרך מובנית למימוש אלגנטי של התבנית הזו.
התבנית כוללת מפרסם שמעלה אירועים ומנויים שמגיבים להם. הנה דוגמה מעשית למעקב אחר מחירי מניות:
public class Stock
{
private decimal _price;
public event Action<decimal> PriceChanged;
public decimal Price
{
get => _price;
set
{
_price = value;
PriceChanged?.Invoke(_price); // הודע לכל הצופים
}
}
}
public class PriceAlert
{
public void OnPriceChanged(decimal newPrice)
{
Console.WriteLine($"Alert: Price is now {newPrice}");
}
}
public class PriceLogger
{
public void OnPriceChanged(decimal newPrice)
{
Console.WriteLine($"Logged: {newPrice}");
}
}מנויים מצרפים את המתודות שלהם לאירוע באמצעות += ויכולים להסיר אותן באמצעות -=:
var stock = new Stock();
var alert = new PriceAlert();
var logger = new PriceLogger();
stock.PriceChanged += alert.OnPriceChanged;
stock.PriceChanged += logger.OnPriceChanged;
stock.Price = 150.50m;
// פלט:
// התראה: המחיר כעת 150.50
// נרשם: 150.50
stock.PriceChanged -= logger.OnPriceChanged; // ביטול הרשמה
stock.Price = 155.00m;
// פלט: התראה: המחיר כעת 155.00תבנית Observer מעודדת צימוד רופף - המחלקה Stock לא צריכה לדעת דבר על הצופים שלה. צופים חדשים יכולים להירשם בלי לשנות את המפרסם, וכך קל להרחיב ולתחזק את המערכת.
אתגר
קלבואו נבנה מערכת לניטור טמפרטורה באמצעות תבנית Observer עם אירועים. תיצרו חיישן שמודיע למספר צופים בכל פעם שהטמפרטורה משתנה — מושלם לתרחישים כמו מערכות בקרת אקלים, שבהן רכיבים שונים צריכים להגיב לעדכוני טמפרטורה.
תארגנו את הקוד בשלושה קבצים:
TemperatureSensor.cs: צרו מחלקהTemperatureSensorבמרחב השמותMonitoring. זהו המפרסם שלכם — הנושא שאובייקטים אחרים יצפו בו. לחיישן שלכם צריכים להיות:- שדה פרטי לאחסון הטמפרטורה הנוכחית
- אירוע בשם
TemperatureChangedשמשתמש ב-Action<double>כדי להודיע למנויים על הטמפרטורה החדשה - מאפיין
Temperatureשמפעיל את האירוע בכל פעם שהטמפרטורה מוגדרת לערך חדש
Observers.cs: צרו שתי מחלקות צופות באותו מרחב שמות, שיירשמו לעדכוני טמפרטורה:DisplayUnit— כוללת מתודהOnTemperatureChanged(double temp)שמדפיסהDisplay: {temp}CAlarmSystem— כוללת מתודהOnTemperatureChanged(double temp)שמדפיסהAlarm Check: {temp}C
Program.cs: חברו הכול יחד על ידי יצירת חיישן ושני הצופים. רשמו את שני הצופים לאירוע של החיישן, ואז עדכנו את הטמפרטורה. לאחר מכן, בטלו את הרישום של מערכת ההתראה ועדכנו שוב את הטמפרטורה כדי להראות שרק יחידת התצוגה מקבלת את ההודעה.
תקבלו שתי קלטים:
- קריאת הטמפרטורה הראשונה (למשל,
22.5) - קריאת הטמפרטורה השנייה (למשל,
28.0)
התוכנית שלכם צריכה:
- ליצור את החיישן ואת שני הצופים
- לרשום את שני הצופים לאירוע
TemperatureChanged - להגדיר את טמפרטורת החיישן לערך הקלט הראשון (שני הצופים אמורים לקבל הודעה)
- לבטל את הרישום של
AlarmSystemלאירוע - להגדיר את טמפרטורת החיישן לערך הקלט השני (רק התצוגה אמורה לקבל הודעה)
לדוגמה, אם הקלטים הם 22.5 ו-28.0, הפלט אמור להיות:
Display: 22.5C
Alarm Check: 22.5C
Display: 28Cהדבר מדגים את העוצמה המרכזית של תבנית Observer — לחיישן לא ידוע ולא אכפת מי מאזין לו. צופים יכולים להירשם ולבטל את הרישום באופן דינמי, והמפרסם פשוט מודיע לכל מי שמאזין כרגע!
נסו בעצמכם
using System;
using Monitoring;
class Program
{
public static void Main(string[] args)
{
// קרא את הטמפרטורות מהקלט
double temp1 = Convert.ToDouble(Console.ReadLine());
double temp2 = Convert.ToDouble(Console.ReadLine());
// TODO: צור מופע של TemperatureSensor
// TODO: צור מופעים של DisplayUnit ו-AlarmSystem
// TODO: רשום את שני המשקיפים לאירוע TemperatureChanged
// TODO: הגדר את טמפרטורת החיישן ל-temp1 (שני המשקיפים יקבלו הודעה)
// TODO: בטל את הרישום של AlarmSystem לאירוע
// TODO: הגדר את טמפרטורת החיישן ל-temp2 (רק DisplayUnit יקבל הודעה)
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמרחבי שמות והנחיותמבוא למחלקות ולאובייקטיםמילת המפתח 'this'מתודות ופרמטריםשדות לעומת מאפייניםבנאיםאתחול אובייקטיםסיכום – מחשבון פשוט4ירושה
תחביר ירושה בסיסית (:)מילת המפתח 'base'מילות המפתח Virtual ו-Overrideמחלקות Sealedמחלקת הבסיס 'object'סיכום – היררכיית עובדים7תכונות מתקדמות
העמסת אופרטוריםאינדקסרים (this[])דריסת ToString()מתודות הרחבהסיכום – רשימה מותאמת אישית10תבניות עיצוב חלק 1
מבוא לתבניות עיצובSingleton בטוח לריבוי תהליכוניםתבנית המפעלתבנית הצופה (אירועים)תבנית האסטרטגיה2מאפיינים וחברים סטטיים
מאפיינים במימוש אוטומטימאפיינים לקריאה בלבד ולכתיבה בלבדשדות ומתודות סטטייםמחלקות סטטיותחברים עם גוף ביטוי5פולימורפיזם וממשקים
פולימורפיזם בזמן קומפילציה לעומת בזמן ריצהממשק לעומת מחלקה מופשטתממשקים מרוביםממשקים מפורשיםהמרה כלפי מעלה והמרה כלפי מטהחזרה: מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה במקום ירושהGenerics (מחלקות ומתודות)נציגים ואירועיםמאפיינים ורפלקציהIDisposable והצהרת usingיסודות הזרקת תלויותתרגלו בעצמכם: קומפיילר C# אונליין