ראשי > adapter pattern > חלק שני
The adapter

המבנה הכללי:
ולהלן המבנה הכללי של ה adapter pattern . באופן מפתיע הוא די דומה לדוגמה שלנו מלמעלה. למי שאינו זוכר כיצד להסתכל בדיאגרמה זו זה הזמן
להתרענן:

לחצו להגדלה
לחץ להגדלה - adapter

למעלה
מיהם החברים בחגיגה?:
  • Target - מגדיר את הממשק הספציפי שלו הקליינט מצפה (ומשתמש).
  • Client - משתף פעולה עם אובייקטים בעלי ממשק זהה לשל target.
  • Adaptee - מגדיר ממשק קיים שצריך לעבור אדפטציה לדרישה מסוימת.
  • Adapter - מבצע לממשק של adaptee אדפטציה ומתאים אותו לממשק של target.
למעלה
מתי נשתמש ב adapter pattern?:
  • כאשר נרצה להשתמש ב class קיים שהממשק שלו לא תואם את הממשק הדרוש.
  • כאשר נרצה ליצור class כללי שניתן לבצע בו reuse והוא צריך לשתף פעולה עם אוסף class ים שאו שהוא לא מכיר, או שאין להם ממשק משותף בינם לבין עצמם. במקרה זה נממש בתוכו adapter בשבילם, ובבוא העת נתאים בין כלclass לבין ה adapter.
  • (עבור object adapter בלבד): כאשר נצטרך להשתמש במספר subclass ים קיימים, וזה לא יהיה פרקטי לבצע אדפטציה לממשק שלהם על ידי ירושת הממשק מכל אחד מהם - נפרט בהמשך.
למעלה
יחסי העבודה:
  • קליינט קורא לפעולות של אובייקט מסוג adapter. כתוצאה מכך, הadapter קורא לפעולות של ה adaptee שמבצעות את הבקשה.
למעלה
יתרונות וחסרונות:
נתייחס ל class adapter ול object adapter בנפרד מכיוון שהם שונים מעט ביתרונותיהם וחסרונותיהם:

Class adapter:
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, ונוכל להתאים את המימוש הפנימי כך שיענה על צרכי שתי האפליקציות. פשוט וקל!
למעלה







 
מה בעמוד:
 
המבנה
המשתתפים
מתי נשתמש
יחסי העבודה
בעד ונגד