Menu
Coddy logo textTech

תבנית המתאם

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

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

challenge icon

אתגר

קל

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

תיצרו שני קבצים כדי לארגן את המימוש של תבנית המתאם:

  • 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() על מקור השמע שלכם והדפיסו את התוצאה
  
}
quiz iconבחנו את עצמכם

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

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

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