תבנית Observer
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Dart של Coddy. שיעור 92 מתוך 110.
תבנית Observer יוצרת קשר של אחד לרבים בין אובייקטים: כאשר אובייקט אחד (הנושא) משנה מצב, כל התלויים בו (הצופים) מקבלים הודעה באופן אוטומטי. התבנית מתאימה במיוחד לתרחישים כמו עדכוני ממשק משתמש, מערכות אירועים או כל מצב שבו חלקים מרובים של היישום שלך צריכים להגיב לשינויים.
התבנית כוללת שני תפקידים מרכזיים: נושא שמנהל רשימה של משקיפים ומודיע להם על שינויים, ומשקיפים שנרשמים ומגיבים לעדכונים:
abstract class Observer {
void update(String message);
}
class NewsAgency {
final List<Observer> _observers = [];
String _latestNews = '';
void subscribe(Observer observer) {
_observers.add(observer);
}
void unsubscribe(Observer observer) {
_observers.remove(observer);
}
void publishNews(String news) {
_latestNews = news;
for (var observer in _observers) {
observer.update(_latestNews);
}
}
}
class NewsChannel implements Observer {
final String name;
NewsChannel(this.name);
@override
void update(String message) {
print('$name received: $message');
}
}
void main() {
var agency = NewsAgency();
var cnn = NewsChannel('CNN');
var bbc = NewsChannel('BBC');
agency.subscribe(cnn);
agency.subscribe(bbc);
agency.publishNews('Breaking news!');
// CNN קיבל: חדשות מתפרצות!
// BBC קיבל: חדשות מתפרצות!
}כאשר קוראים ל־publishNews, הסוכנות עוברת על כל הצופים הרשומים ומפעילה את המתודה update שלהם. צופים יכולים להירשם או לבטל את הרשמתם בכל עת, וכך המערכת נשארת גמישה ובעלת צימוד רופף — הנושא לא צריך להכיר את הסוגים הספציפיים של הצופים שלו.
אתגר
קלבואו נבנה מערכת להתראות על מחירי מניות באמצעות תבנית Observer! תיצור מערכת שבה טיקר מניות מודיע לכמה משקיעים בכל פעם שהמחיר משתנה, וכך כל משקיע יכול להגיב לעדכוני השוק בדרכו שלו.
תארגן את הקוד שלך בשני קבצים:
stock_system.dart: צור כאן את מערכת התצפית שלך:- מחלקה מופשטת
Investorעם מתודהvoid onPriceChange(String stockName, double price) - מחלקה
DayTraderשמממשת אתInvestor. יש לה שדהname, ומתודתonPriceChangeשלה מדפיסה:[name] sees [stockName] at $[price] - Making quick trade! - מחלקה
LongTermInvestorשמממשת אתInvestor. יש לה שדהname, ומתודתonPriceChangeשלה מדפיסה:[name] notes [stockName] at $[price] - Holding steady. - מחלקה
StockTicker(הנושא) עם:- שדה
String stockName - רשימה פרטית לאחסון משקיעים שנרשמו
- מתודת
subscribe(Investor investor)להוספת משקיע - מתודת
unsubscribe(Investor investor)להסרת משקיע - מתודת
updatePrice(double newPrice)שמודיעה לכל המשקיעים שנרשמו על המחיר החדש
- שדה
- מחלקה מופשטת
main.dart: ייבא את מערכת המניות שלך והדגם את תבנית Observer בפעולה:- צור
StockTickerעבור מניה בשםDART - צור
DayTraderבשםAliceו-LongTermInvestorבשםBob - רשום את שני המשקיעים לטיקר
- עדכן את המחיר ל-
150.50(יש להודיע לשני המשקיעים) - הדפס שורה ריקה
- בטל את הרישום של Alice מהטיקר
- עדכן את המחיר ל-
155.75(כעת יש להודיע רק ל-Bob)
- צור
הדוגמה הזו ממחישה כיצד תבנית Observer יוצרת מערכת עם צימוד רופף — StockTicker לא צריך לדעת אם הוא מודיע לסוחרי יום או למשקיעים לטווח ארוך; הוא פשוט קורא ל-onPriceChange עבור כל מי שנרשם!
הפלט הצפוי:
Alice sees DART at $150.5 - Making quick trade!
Bob notes DART at $150.5 - Holding steady.
Bob notes DART at $155.75 - Holding steady.נסו בעצמכם
import 'stock_system.dart';
void main() {
// TODO: צרו StockTicker עבור מניה בשם 'DART'
// TODO: צרו DayTrader בשם 'Alice'
// TODO: צרו LongTermInvestor בשם 'Bob'
// TODO: רשמו את שני המשקיעים לעדכונים מהטיקר
// TODO: עדכנו את המחיר ל-150.50 (שני המשקיעים אמורים לקבל הודעה)
// TODO: הדפיסו שורה ריקה
// TODO: בטלו את המנוי של Alice לעדכונים מהטיקר
// TODO: עדכנו את המחיר ל-155.75 (רק Bob אמור לקבל הודעה כעת)
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםספריות וייבואמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותמשתני מופעיסודות הבנאיחזרה: מחשבון פשוט4בטיחות מפני ערכי null
מבוא לבטיחות מפני ערכי nullניתן להקצאה ל-null לעומת לא ניתן להקצאה ל-nullהאופרטורים ? ו-!מילת המפתח Late ובטיחות מפני ערכי nullאופרטורים מודעי nullבטיחות מפני ערכי null במחלקותסיכום – מערכת פרופילי משתמשים7מחלקות מופשטות וממשקים
מחלקות מופשטותמתודות מופשטותממשקים ב-Dartממשקים משתמעיםמימוש לעומת הורשהממשקים מרוביםחזרה – מחשבון צורות10אוספים וגנריות
סקירה כללית של List, Set ו-Mapאוספים בטוחים מבחינת טיפוסיםמחלקות גנריותמתודות גנריותאילוצים גנרייםIterable ו-Iteratorסיכום – אחסון גנרי13מושגי OOP מתקדמים
הרכבה לעומת הורשהמתודות הרחבהמחלקות קריאותמחלקות אטומות (Dart 3)רשומות (Dart 3)תבניות והתאמה (3.0)טיפוסים מונים עם מתודות16פרויקט: ניהול ספרייה
סקירת הפרויקטמחלקות ספר ומשתמש2בנאים ב-Dart
בנאי ברירת מחדלבנאים בעלי שםרשימות אתחולבנאים קבועיםבנאי Factoryבנאים מפניםסיכום - בונה צורות5כימוס
חברים ציבוריים לעומת פרטייםמוסכמת הקידומת _פרטיות ברמת הספרייההעמקה ב-getters וב-settersהסתרת מידעסיכום – רשומות תלמידים8מיקסינים
מבוא למיקסיניםיצירת מיקסיניםשימוש במספר מיקסיניםמילת המפתח on במיקסיניםמיקסינים לעומת ירושהמיקסינים לעומת ממשקסיכום – מערכת בעלי החיים3מאפייני מחלקה
איברי מופע לעומת איברים סטטייםשדות final ו-constמשתני lateמתודות ושדות סטטייםGetters ו-Settersסיכום – מנהל חשבונות בנק6ירושה
ירושה בסיסיתמילת המפתח superדריסת מתודותהאנוטציה @overrideמילת המפתח final למחלקהבנאים וירושהסיכום – היררכיית עובדים9פולימורפיזם
יסודות הפולימורפיזםפולימורפיזם באמצעות ממשקיםבדיקת טיפוסים בזמן ריצההאופרטורים is ו-asמילת המפתח קווריאנטיסיכום — מעבד תשלומים12תכנות מונחה עצמים אסינכרוני
Future-ים ו-async/awaitיסודות ה-Streamsבקרי Streamsבנאים אסינכרונייםאסינכרוניות במתודות של מחלקהסיכום - אחזור נתוניםתרגלו בעצמכם: קומפיילר Dart אונליין