תבנית המתאם
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 71 מתוך 87.
תבנית המתאם היא תבנית עיצוב מבנית שמאפשרת לממשקים שאינם תואמים לעבוד יחד. היא משמשת כגשר בין שתי מחלקות, וממירה את הממשק של מחלקה אחת לממשק שהלקוח מצפה לו. חשבו עליה כמו על מתאם חשמל שמאפשר לחבר מכשיר אירופי לשקע אמריקאי.
דמיין שיש לך ממשק MediaPlayer קיים שמנגן קובצי שמע, אבל עליך לשלב ספרייה של צד שלישי שמשתמשת בממשק שונה לחלוטין להפעלת סרטונים:
// ממשק קיים שהקוד שלך משתמש בו
interface MediaPlayer {
void play(String filename);
}
// מחלקה של צד שלישי עם ממשק לא תואם
class AdvancedVideoPlayer {
public void playVideo(String filename) {
System.out.println("Playing video: " + filename);
}
}המתאם עוטף את המחלקה שאינה תואמת ומממש את הממשק הצפוי, תוך תרגום הקריאות ביניהם:
class VideoPlayerAdapter implements MediaPlayer {
private AdvancedVideoPlayer videoPlayer;
public VideoPlayerAdapter() {
this.videoPlayer = new AdvancedVideoPlayer();
}
public void play(String filename) {
videoPlayer.playVideo(filename);
}
}עכשיו קוד הלקוח שלך יכול להשתמש בנגן הווידאו דרך הממשק המוכר MediaPlayer:
MediaPlayer player = new VideoPlayerAdapter();
player.play("movie.mp4"); // פלט: מנגן סרטון: movie.mp4תבנית המתאם שימושית מאוד בעת שילוב קוד מדור קודם או ספריות של צד שלישי, בלי לשנות את קוד המקור שלהן. הלקוח אינו מודע לכך שהוא עובד עם מחלקה שעברה התאמה. הוא פשוט משתמש בממשק שהוא מכיר.
אתגר
קלבוא נבנה מערכת להמרת טמפרטורות באמצעות תבנית המתאם! יש לך יישום מזג אוויר קיים שעובד עם טמפרטורות בצלזיוס, אבל עליך לשלב חיישן טמפרטורה ישן שמפיק קריאות רק בפרנהייט. במקום לשנות אחת מהמערכות, תיצור מתאם שיגשר ביניהן.
תארגן את הקוד שלך בארבעה קבצים:
TemperatureProvider.java: הגדר את הממשק שיישום מזג האוויר שלך מצפה לו. עליו להצהיר על מתודהgetTemperatureCelsius()שמחזירה ערך מסוג double המייצג את הטמפרטורה בצלזיוס.FahrenheitSensor.java: מחלקה זו מייצגת את החיישן הישן, בעל הממשק שאינו תואם. צור מחלקה עם שדה פרטי מסוג double עבור הטמפרטורה בפרנהייט, שנקבע באמצעות הבנאי. צריכה להיות בה מתודהreadFahrenheit()שמחזירה את ערך הפרנהייט השמור.SensorAdapter.java: צור את המתאם שהופך את חיישן הפרנהייט לתואם ליישום מזג האוויר שלך. על המתאם שלך לממש אתTemperatureProviderולעטוףFahrenheitSensor. כשקוראים ל-getTemperatureCelsius(), עליו לקרוא את הערך מהחיישן ולהמיר אותו לצלזיוס באמצעות הנוסחה:(fahrenheit - 32) * 5 / 9.Main.java: חבר את כל החלקים יחד! תקבל קלט אחד: קריאת טמפרטורה בפרנהייט (double).צור
FahrenheitSensorעם ערך הקלט. לאחר מכן צורSensorAdapterשעוטף את החיישן הזה. אחסן את המתאם במשתנה מסוגTemperatureProviderכדי להדגים שיישום מזג האוויר שלך יכול להשתמש בו דרך הממשק הצפוי.הדפס את התוצאה בפורמט הזה:
Temperature: [celsius] Cכאשר celsius מעוגל למקום אחד אחרי הנקודה העשרונית.
תקבל קלט אחד: הטמפרטורה בפרנהייט (double).
לדוגמה, עבור הקלט 98.6, הפלט יהיה:
Temperature: 37.0 Cשים לב שמחלקת Main שלך עובדת אך ורק עם הממשק TemperatureProvider. היא אינה יודעת שהטמפרטורה בפועל מגיעה מחיישן פרנהייט שמותאם מאחורי הקלעים. זו האלגנטיות של תבנית המתאם!
נסו בעצמכם
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double fahrenheit = scanner.nextDouble();
// TODO: צור FahrenheitSensor עם ערך הקלט
// TODO: צור SensorAdapter שעוטף את החיישן
// TODO: אחסן את המתאם במשתנה מסוג TemperatureProvider
// TODO: קבל את הטמפרטורה בצלזיוס והדפס אותה
// תבנית: "Temperature: [celsius] C" עם ספרה אחת אחרי הנקודה העשרונית
// רמז: השתמש ב-String.format("%.1f", value) לעיצוב
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותשדות (מאפיינים)מתודת הבנאיהעמסת בנאיםחזרה – מחשבון פשוט4ירושה
ירושה בסיסית (extends)מילת המפתח superדריסת מתודות (@Override)שרשור בנאיםהמחלקה Objectירושה יחידה ורב־רמתיתלמה אין ירושה מרובה של מחלקותסיכום – היררכיית עובדים7מתודות מיוחדות ומחלקת Object
מתודת toString()equals() ו-hashCode()מתודת clone()compareTo() ו-Comparableהממשק Comparatorסיכום – מיון מותאם אישית2מצייני גישה ואנקפסולציה
סקירה של רמות הגישהמתודות Getter ו-Setterהסתרת מידעמילת המפתח finalסיכום – מנהל חשבון בנק5פולימורפיזם
יסודות העמסת מתודותדריסת מתודות (בזמן ריצה)המרה כלפי מעלה וכלפי מטההאופרטור instanceofמחלקות ומתודות מופשטותסיכום – מחשבון צורות8מושגי OOP מתקדמים
הרכבה מול ירושהאגרגציה מול הרכבהמחלקות פנימיות, מקוננות ואנונימיותEnums ומתודות של EnumRecords (Java 16+)מחלקות חתומות (Java 17+)3מאפייני מחלקה וחברים סטטיים
משתני מופע לעומת משתנים סטטייםמתודות סטטיותבלוקים סטטייםקבועים (static final)סיכום — מונה ומחלקת עזר6ממשקים ומחלקות מופשטות
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםמתודות ברירת מחדל וסטטיות בממשקמחלקות מופשטות לעומת ממשקיםממשקים פונקציונלייםסיכום – מערכת תשלומים9גנריות
מבוא לגנריותמחלקות גנריותשיטות גנריותפרמטרי טיפוס מוגבליםתווים כלליים (?, extends, super)סיכום – מכל גנרי12תבניות עיצוב — חלק 2
תבנית הפקודהתבנית המתאםתבנית העיצובתבנית המתודה התבניתיתתבנית המצבתבנית המרוכבתתבנית האיטרטורתרגלו בעצמכם: קומפיילר Java אונליין