תבנית המתאם
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Dart של Coddy. שיעור 95 מתוך 110.
תבנית המתאם מאפשרת לממשקים שאינם תואמים לעבוד יחד. היא משמשת גשר בין שתי מחלקות שלא היו יכולות לשתף פעולה אחרת, ועוטפת מחלקה קיימת בממשק חדש שהלקוחות מצפים לו. הדבר שימושי במיוחד בעת שילוב ספריות של צד שלישי או קוד מדור קודם ביישום שלך.
דמיין שיש לך מערכת שעובדת עם נתוני JSON, אבל עליך לשלב רכיב שמפיק XML בלבד. במקום לשנות אחת מהמחלקות, צור מתאם שמתרגם ביניהן:
// הממשק הקיים שהמערכת שלך מצפה לו
abstract class JsonData {
String getJson();
}
// מחלקה ישנה עם ממשק לא תואם
class XmlService {
String getXml() {
return '<data><name>John</name></data>';
}
}
// המתאם הופך את XmlService לתואם ל-JsonData
class XmlToJsonAdapter implements JsonData {
final XmlService _xmlService;
XmlToJsonAdapter(this._xmlService);
@override
String getJson() {
String xml = _xmlService.getXml();
// המרת XML ל-JSON (בצורה פשוטה)
return '{"name": "John"}';
}
}
void main() {
var xmlService = XmlService();
var adapter = XmlToJsonAdapter(xmlService);
print(adapter.getJson()); // {"name": "John"}
}ה־XmlToJsonAdapter עוטף את XmlService ומממש את הממשק JsonData. קוד הלקוח עובד עם הממשק המוכר JsonData בלי לדעת שהנתונים הגיעו במקור ממקור XML. המתאם מטפל בכל התרגום באופן פנימי.
השתמש בתבנית המתאם כשרוצים להשתמש במחלקה קיימת, אבל הממשק שלה אינו תואם למה שדרוש, או כשרוצים ליצור מחלקה לשימוש חוזר שמשתפת פעולה עם מחלקות בעלות ממשקים שאינם תואמים.
אתגר
קלבואו נבנה מערכת מתאם לנגן מדיה! דמיינו שיש לכם מערכת שמע מודרנית שמצפה מכל מקורות המדיה לספק שמע דרך ממשק סטנדרטי, אבל אתם צריכים לשלב נגן תקליטי ויניל מיושן, שמפיק צליל בדרך שונה לחלוטין.
תיצרו שני קבצים כדי לארגן את המימוש של תבנית המתאם:
media_adapter.dart: הקובץ הזה מכיל את הממשק ואת מחלקות המתאם שלכם. הגדירו מחלקה מופשטת בשםAudioSourceשהמערכת המודרנית שלכם מצפה לה — צריכה להיות לה מתודה בשםString playAudio()שמחזירה את פלט השמע כמחרוזת. לאחר מכן, צרו מחלקה בשםVinylPlayerשמייצגת את הציוד הישן — יש לה שדה בשםtrackNameומתודה בשםString spinRecord()שמחזירה את*crackle* Playing vinyl: [trackName] *crackle*. לבסוף, בנו מתאם בשםVinylAdapterשמממש אתAudioSourceועוטף אובייקט מסוגVinylPlayer. המתודהplayAudio()של המתאם צריכה לקרוא למתודהspinRecord()של נגן הוויניל ולהחזיר את התוצאה — וכך לגשר בין הממשקים שאינם תואמים.main.dart: ייבאו את קובץ מתאם המדיה שלכם והדגימו כיצד המתאם מאפשר לנגן הוויניל הישן לעבוד עם קוד שמצפה לממשק המודרניAudioSource. צרו אובייקט מסוגVinylPlayerעם שם הרצועהBohemian Rhapsody. לאחר מכן, צרו מתאם מסוגVinylAdapterשעוטף את נגן הוויניל הזה. שמרו את המתאם במשתנה מסוגAudioSourceכדי להוכיח שהוא תואם לממשק המצופה. קראו למתודהplayAudio()במקור השמע שלכם והדפיסו את התוצאה.
היופי בתבנית הזאת הוא שהקוד הראשי שלכם עובד עם הממשק הסטנדרטי AudioSource — הוא לא צריך לדעת שמאחורי הקלעים, נגן ויניל ישן הוא זה שעושה את העבודה בפועל!
פלט צפוי:
*crackle* Playing vinyl: Bohemian Rhapsody *crackle*נסו בעצמכם
import 'media_adapter.dart';
void main() {
// TODO: צרו VinylPlayer עם שם הרצועה "Bohemian Rhapsody"
// TODO: צרו VinylAdapter שעוטף את נגן הוויניל
// TODO: שמרו את המתאם במשתנה מסוג AudioSource
// TODO: קראו ל-playAudio() על מקור השמע שלכם והדפיסו את התוצאה
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
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בנאים אסינכרונייםאסינכרוניות במתודות של מחלקהסיכום - אחזור נתונים15תבניות עיצוב חלק 2
תבנית הפקודהתבנית המתאםתבנית העיצובןתבנית שיטת התבניתתבנית המצבתבנית המרוכבתבנית המאגרתרגלו בעצמכם: קומפיילר Dart אונליין