סוגיה בעיצוב OO
התחלתי לעשות לאחרונה סוג מסויים של refactoring שלא מצאתי תעוד לגביו בשום מקום ואני תוהה על טיבו. אני אקרא לו - "Replace Subtyping with Abstract Factory". העניין הוא שיש לי ממשק כללי וממשק נוסף שנראה שהוא מכיל את הממשק הכללי. דוגמא:
התחלתי לעשות לאחרונה סוג מסויים של refactoring שלא מצאתי תעוד לגביו בשום מקום ואני תוהה על טיבו. אני אקרא לו - "Replace Subtyping with Abstract Factory". העניין הוא שיש לי ממשק כללי וממשק נוסף שנראה שהוא מכיל את הממשק הכללי. דוגמא:
public interface Printable { void print(Printer toThisPrinter); } public interface Document { void openIn(Editor editor); }
עכשיו אני רוצה להגדיר שכל מסמך הוא גם ניתן להדפסה. דרך אחת לעשות זאת היא להוסיף מתודת print גם למסמך (וביישום אפשר לעבוד עם Printable ואפשר גם לא), אבל אז אני קצת מאבד את ה reuse במתודת ה print משום שאני לא יכול להתייחס למסמך כ Printable בשום הקשר. הדרך השני היא ליצור קשר של הורשה בין Document ל Printable. על פניו הכל טוב ויפה - כל יישום של Document חייב ליישם Printable ואני יכול להתייחס אליו בהתאם. אבל, מה עם הממשקים היו גדולים יותר? ומה עם בנוסף ל Printable המסמך שלי הוא גם Browseable וכו'... אני מגיע למצב של ממשק גדול מדי שצריך ליישם בכל מחלקה. אז הפתרון שחשבתי עליו הוא להחליף את הורשת הממשקים ב Abstract Factory באופן הבא:public interface Document { void openIn(Editor editor); Printable getPrintable(); }
מה הרווחתי? עכשיו אני יכול לבחור בכל יישום של Document בין 3 אפשרויות: 1. ליישם גם את Printable ולהחזיר this במתודת getPrintable. 2. ליישם את Printable כ Inner Class (שאולי לא חייב לממש את כולו אלא לרשת מ AbstractPrintable כלשהוא) ולהחזיר אותו. 3. לאתחל אובייקט אחר שמיישם Printable ולהחזיר אותו. אז יש לי יותר גמישות ואני גם חוסך קוד ובפוטנציה יש לי פחות מחלקות לערוך כשאעשה שינויים בממשק Printable. (קשה קצת לראות את זה בדוגמא הפשטנית אבל צריך לדמיין שיש ל Printable יותר מתודות...). מצד שני, העברת מתודות בין ממשק אחד לשני נעשית קשה יותר. אשמח לשמוע אם מישהו התמודד עם סוגיה זו והאם יש השלכות בעייתיות שאני מפספס במודל הזה. או לחילופין אם מדובר ב refactoring מוכר ומתועד שפשוט לא הצלחתי למצוא...