180 likes | 298 Views
Design Patterns. תכנות מתקדם 89-210 תרגול מספר 10 תשע"א 2010-2011. אליהו חלסצ'י. היום נלמד על Structural Patterns . SP עוסקים בשאלה כיצד מחלקות ואובייקטים מורכבים יחדיו כדי ליצור מבנים גדולים יותר. נעבור על: Adapter Bridge Composite Decorator Façade Flyweight Proxy. הקדמה. Adapter.
E N D
Design Patterns תכנות מתקדם 89-210תרגול מספר 10 תשע"א 2010-2011 אליהו חלסצ'י
היום נלמד על Structural Patterns. SP עוסקים בשאלה כיצד מחלקות ואובייקטים מורכבים יחדיו כדי ליצור מבנים גדולים יותר. נעבור על: Adapter Bridge Composite Decorator Façade Flyweight Proxy הקדמה
Adapter • בעיה: • ה client יודע לעבוד דרך ממשק אחד, ואילו לנו יש מחלקה עם ממשק אחר • או מתודות אחרות. • להתחיל לשנות את הממשק של ה client כך שיתאים למחלקה שלנו יגרור המון שינויים בשאר המחלקות המממשות ממשק זה. • אותו הדבר יקרה אם אשנה את הממשק של המחלקה שלנו... • כיצד נפתור את הבעיה?
Adapter • פיתרון: • דרך אחת תהיה לממש את שני הממשקים • ואז במתודה run נפעיל את play. • אבל הדבר מפריע למחלקה MP3Player • להיות מחלקה שמתעסקת רק עם mp3 • מה יקרה אם יהיו עוד ממשקים לממש?? • המצב רק יחמיר. • פיתרון טוב יותר יהיה להשתמש ב Adapter • יש שני סוגים: • Object Adapter • Class Adapter
Adapter פיתרון: Object Adapter ניצור מחלקה של Runnable שמחזיקה Reference לאובייקט ה MP3Player ובמתודה run נפעיל את ה play שלו. Object Adapter Class Adapter ניצור מחלקה של Runnable שיורשת גם מ MP3Player, ובמתודה run נפעיל את super.play() Class Adapter
Adapter המבנה הכללי: Class Adapter אפשרי למימוש ב ++C. אפשרי ב Java רק אם ה Target הוא ממשק. Object Adapter דרך יותר מקובלת ב Java. שאלות: 1. איזה adapter מסוגל לעבוד לבדו עם כל סוג של adaptee? 2. באיזה adapter יותר קל לשנות את התנהגות ה adaptee ?
StrawBigHouse WoodBigHouse BrickBigHouse Bridge מטרה: יצירת הפרדה בין האבסטרקציה לבין האימפלמנטציה כך ששתיהן תוכלנה להשתנות ללא תלות אחת בשנייה. דוגמא לבעיה: נתונה המחלקה האבסטרקטית house המייצגת בית, יש שלוש דרכים לבנות בית: קש, עץ ולבנים. אז הגיוני שנממש אותה בשלושת הדרכים: אבל מה יקרה אם נרצה בית נוסף? House StrawHouse WoodHouse BrickHouse BigHouse
Bridge פיתרון: נפתור את זה ע"י הפרדה בין האבסטרקציה House לאימפלמנטציה HouseImp מחלקות שמגדירות צורות שונות של בית יורשות מ House את המתודות שממומשות ע"י מופע של HouseImp.
Bridge מבנה: • נשתמש ב Bridge כאשר: • נרצה לנתק את הקשר בין המימוש לאבסטרקציהלדוג' כשנרצה להחליף מימוש בזמן ריצה. • גם האבסטרקציה וגם המימוש אמורים להיותמורחבים ע"י ירושה. • לא נרצה ששינוי במימוש האבסטרקציה ישפיע על ה client, כלומר לא נדרש לקמפל מחדש את הקוד. • יש צורך לשתף מימוש בין מס' אובייקטים,ולהסתיר זאת מה client. • השלכות: • הפרדה זו מאפשרת להחליף אבסטרקציה בזמן ריצה ואף להחליף את האימפלמנטציה בזמן ריצה. • הפרדה זו מעודדת "שכבות" וכך מובילה ל design יותר טוב של המערכת – השכבה הגבוהה יותרמכירה רק את abstraction ואת implementor. • יכולת הרחבה משופרת – ניתן להרחיב (ירושה) גם את האימפלמנטציהוגם את האבסטרקציה בנפרד. • הסתרת המימוש מה client.
Composite • מטרה: • הרכבת אובייקטים למבנה של עץ המייצג היררכיה של חלק-שלם, Composite מאפשר • ל client להתייחס באותה הצורה לאובייקט אינדיבידואלי ולהרכבה של אובייקטים. • השלכות: • ה DP מגדיר היררכית מחלקות שמכילותprimitive objects (עלים) וגם composite objects(קודקוד עם ילדים) בצורה בה רקורסיבית ניתןלהרחיב אותם לעץ מורכב, בפשטות. • ה client לא יודע (וגם לא צריך להיות איכפת לו)אם יש לו leaf או composite, ולכן זה הופך אתהקוד שלו להרבה יותר פשוט. • קל מאד להוסיף סוגים חדשים של leaf אוcomposite כי זה לא משנה ל client. • חיסרון: בגלל שקל מאד להוסיף סוגים חדשים,קשה לאכוף הגבלות – כשלדוגמא רוצים רקרכיבים מסוימים, נצטרך לבצע בדיקות בזמןריצה.
Decorator • מטרה: • הוספה דינאמית של אחריות לאובייקט. • ה Decorator מהווה תחליף דינאמי וגמיש ליורשה, עבור פונקציונאליות מורחבת. • מתי נשתמש: • כשרוצים להוסיף אחריותבאופן דינאמי, ואף שקוףלאובייקטים אחרים. • עבור אחריות שיש להסיר • כאשר הרחבה ע"י ירושהאינה מעשית בגלל מספררב של אופציות, הגדרותמחלקה חבויות, או חוסראפשרות לרשת ממנה. • N תוספות בת"ל יוצרות 2N אפשרויות שהיינו צריכים לממש ע"י ירושה, • או רק N מחלקות של Decorators.
Decorator • השלכות: • ה Decorator מאפשר הרבה יותר גמישות מאשר ירושה, ניתן להוסיף ולהסיר אחריותבזמן ריצה פשוט ע"י הצמדה או הפרדה שלו, בעוד שבירושה הינו צריכים ליצור מחלקה עבורכל קומבינציה של תוספת אחריות. • ניתן לערבב תוספות של אחריות כרצוננו, ואף להוסיף אחריות כלשהי כמה פעמים. (לדוג' גבולכפול לשדה הטקסט) • בהרחבה ע"י ירושה נצטרך לשלם מראש עבור כל האופציות גם אם לא נשתמש בכולן בעודשב Decorator נוסיף אחריות תוך כדי ריצה ונשלם רק על מה שצריך. • ה Decorator לא חייב להיות זהה לרכיב שהוא מחזיק ולכן אין לסמוךעל כך כשמקבלים Decorator... • ניתן להגיע למצב בו יש לנו המון מחלקות קטנטנותבעוד שקל לכייל ולדבג אותן למי שמבין אותן,לאחרים יהיה קשה.
ממשק ממשק ממשק ממשק ממשק ממשק ממשק ממשק Façade מטרה: מטרתו להוות ממשק יחיד לכמה ממשקים שונים בתת-מערכת מורכבת כלשהי. ה façade מגדיר ממשק high-level ובכך מקל על העבודה עם תת-המערכת. לתכנן מערכת מורכבת כאוסף של תת-מערכות זה design נכון, ומטרה נפוצה היא לצמצם ככל הניתן את התקשורת והתלות בין תת-המערכות הללו, וניתן להשיג זאת באמצעות ה façade. לדוגמא: יש לנו תת-מערכת לקימפול קוד היא בנויה ממחלקות כגון Parser, Laxer, SymbolTable , ByteCode ועוד. אולי יש clients שצריכים גישה ישירה למחלקות אלו, אך רוב ה clients רוצים פשוט לקמפל. המחלקה Compiler מהווה façade.
Flyweight בעיה: אנו רוצים לממש משחק סודוקו, והגיוני שנצטרך אובייקט לייצוג ספרה בלוח. נשתמש בממשק Digit: כמה מופעים של Digit נצטרך? נצטרך 81 מופעים של digit, ואף כפול אם נרצה לזכור גם את הפיתרון... המצב אף יחמיר בלוח סודוקו גדול יותר. כיצד נפתור?
Flyweight • פיתרון: • נפריד ב Digit בין state פנימי – intrinsic, שיכול להיות • משותף, לבין sate חיצוני – extrinsic, שאינו בר שיתוף. • הספרות 9..1 יכולות להיות • משותפות אך מיקום הספרה לא. • נסתפק ב 9 מופעים של Digit בלבד, כאשר כל תא • בלוח הסודוקו יצביע אל המופע המשותף המתאים. • כדי להדפיס ספרה במקום הנכון נעביר את השורה • והעמודה כפרמטרים – שכן הם חיצוניים ואינם ניתנים • לשיתוף. • דוגמאות לסביבות נוספות: • מעבד תמלילים. • כריית טקסט. • סיווג טקסטים. Flyweight pool
Flyweight • מטרה: • להשתמש בשיתוף כדי לתמוך במספר גדול של אובייקטים קטנים בצורה יעילה. • השלכות: • אולי מבזבזים זמן על חישוב extrinsic states • אך המון מקום נחסך ע"י שיתוף. • רמת החיסכון מושפעת מהגורמים הבאים: • ההפרש בין מספר האובייקטים שהיו נוצריםללא ה DP הזה. • כמות ה intrinsic states בכל אובייקט. • האם ה extrinsic statesמחושבים או שמורים.
Proxy • מטרה: • מתן ממלא מקום עבור אובייקט כלשהו, באמצעות ממלא המקום נשלטת הגישה לאובייקט. • מדוע צריך ממלא מקום זה? • לעיתים יש צורך במצביע מתוחכם או רב תכליתי לאובייקט: • Remote Proxy מתן ייצוג מקומי עבור אובייקטבמרחב כתובות אחר. • Virtual Proxy יוצר אובייקטים "יקרים" ע"פ דרישה. • Protection Proxy בודק הרשאות גישה לאובייקט. • Smart referenceמבצע פעולות נוספותכשיש בקשת גישה לאובייקט, כגון מונה מספר גישות, טעינתו לזיכרון בעתהגישה הראשונה או מניעה מאובייקטים אחרים לגשת אליו.
מדוע נרצה להשתמש ב facade ? האם ניתן להפריד בין האבסטרקציה לאימפלמנטציה? מתי נעדיף להרחיב מחלקה ע"י ירושה, ומתי נעדיף וכיצד נרחיב אותה דינאמית? מנה יתרונות וחסרונות ל Decorator Pattern. האם ה Composite מתאים גם לייצוג של גרף? חישבו על DP שיתאים לניהול Cache. הטמעה