כאשר נרצה ליצור class כללי שניתן לבצע בו reuse והוא צריך לשתף פעולה עם אוסף class
ים שאו שהוא לא מכיר, או שאין להם ממשק משותף בינם לבין עצמם. במקרה זה נממש בתוכו adapter בשבילם, ובבוא העת נתאים בין כלclass לבין ה adapter.
(עבור object adapter בלבד): כאשר נצטרך להשתמש במספר subclass ים קיימים, וזה לא יהיה פרקטי לבצע אדפטציה לממשק שלהם על ידי ירושת הממשק מכל אחד מהם - נפרט בהמשך.
יש אפשרות ל adapter לבצע דריסה של פעולות מסוימות ב adaptee מכיוון שהוא subclass של ה adaptee.
התוצאה הסופית היא אובייקט אחד ואין צורך ב indirection על מנת להגיע ל adaptee.
Object adapter:
ישנה אפשרות ש adapter אחד יעבוד עם הרבה adaptees- כלומר הadaptee עצמו וכל subclass שלו (כי בביצוע ההרכבה הפוינטר אליו יכול לקבל כל subclass שלו. כמו כן, ה adapter יכול להוסיף פונקציונליות לכל ה adaptees בבת אחת).
קשה יותר לדרוס פעולות של adaptee. זה ידרוש ליצור subclass לadaptee עצמו, ולבצע את האדפטציה עליו.
נושאים אחרים שיש להתייחס אליהם:
כמה אדפטציה adapter מבצע?: adapter ים שונים מבצעים כמות עבודה שונה כדי להתאים adaptee לממשק target.
במקרה הפשוט מה שמתבצע הוא שינוי שמות הפעולות ובמקרים מסובכים יותר תמיכה בקבוצת פעולות שונה לגמרי. כמות העבודה המתבצעת תלויה בכמה דומה ממשק הtarget לזה של ה adaptee.
Pluggable adapters: בעקרון, class הוא יותר reusable ככל שמקטינים את ההנחות ש class
ים אחרים צריכים להניח לגביו על מנת להשתמש בו. על ידי בניית interface-adaptation לתוכו, מבטלים את ההנחה ש class
ים שירצו להשתמש בו יצטרכו לעשות זאת דרך ממשק מסוים (או דרך אותו ממשק). כלומר, זה מאפשר לנו לשלב אותו במערכות קיימות שיכולות לצפות לממשק שונה לגמרי ממנו. יש הקוראים ל
class כזה pluggable adapter.
חישבו כדוגמה על class שנקרא TreeDisplay ויודע להציג מבנים שבנויים כעץ בצורה גרפית. אם TreeDisplay היה
class שהוא ספציפי לאפליקציה מסוימת אזי היינו דורשים שכל האובייקטים שהוא יציג גרפית יהיו בעלי אותו ממשק, למשל יורשים מ
abstract class שנקרא Tree. עם זאת, כשאנו כותבים קוד נרצה שיהיה כמה שיותר שמיש, כדי שנוכל למחזר אותו ולחסוך לעצמנו עבודה בעתיד.
לכן לא נרצה להגביל אותו לשימוש בממשק מסוים.
אפליקציות שונות מגדירות לעצמן בצורות שונות את ה class ים עבור מבנה של עץ ולכן לאפליקציות שונות רב הסיכוי שהממשק שלהם עבור Tree structure שונה. למשל, אם המבנה מייצג directory אז הגישה לילדים של צומת יכולה להיות דרך פקודת
GetSubDirectories(), בעוד שבמבנה שמתאר היררכית הורשה הפקודה יכולה להיקרא GetSubclasses().
אם נרצה ש TreeDisplay שלנו יהיה reusable נדאג שידע להציג היררכיות שונות במבנה עץ אפילו אם הן משתמשות בממשקים שונים, כלומר נבנה לתוכו interface adaptation. בהמשך נראה כיצד נעשה זאת.
שימוש ב two way adapters כדי למנוע תלות:
בעיה פוטנציאלית של adapter ים היא שהם אינם שקופים לכל ה clients. אובייקט שעבר אדפטציה אינו נושא את הממשק הישן שלו ולכן לא ניתן להשתמש בו בכל מקום במקום האובייקט המקורי.
two-way adapters פותרים בעיה זו. הם שימושיים במיוחד כאשר שני clients שונים צריכים להסתכל על אובייקט בצורה שונה. נלמד מהם דרך דוגמה: באפליקציה א' קיים אובייקט obj1 והיא מעבירה אותו מדי פעם לאפליקציה ב' כחלק מהתקשורת ביניהם (למשל אם obj1 מתאר מצב רגעי כלשהו).
כנ"ל לאפליקציה ב' יש אובייקט שמתאר מצב רגעי בה ונקרא obj2, והיא מעבירה אותו מדי פעם לאפליקציה א'. obj1 ו obj2 מתארים דברים מאוד דומים אך הממשק שלהם שונה. אפליקציה א' מכירה רק ממשק כמו של obj1 ואפליקציה ב' מכירה רק ממשק כמו של obj2, אך הן עדיין צריכות להעביר כל אחת את המצב שלה לשנייה.
הפתרון הוא, כפי שניחשתם, two-way adapter. אך מהו? ובכן, הוא יהיה אובייקט שיורש הורשה מרובה
( public inheritance) מ obj1 ומobj2 .
כך יהיו לו את שני הממשקים, של obj1 ושל obj2, ונוכל להתאים את המימוש הפנימי כך שיענה על צרכי שתי האפליקציות. פשוט וקל!