Factory Method / Abstract Factory

user214

New member
Factory Method / Abstract Factory

חברי הפורום הנכבדים, יש לי שאלה. מטרתם של שני ה - patterns הנ"ל היא "לפשט" יצירה של אובייקטים, לגרום לכך, שבמערכות שונות יווצרו אוביקטים המתאימים למערכת, בעלי אותה הפונקציונאליות. היכן, אכן, ייקבע, מהו ה - factory המתאים? האם בצורה hard-coded (והנאיבית) כגון: CFactory* pcWidgetFactory = new CLinuxWidgetFactory או, מה שלי נראה, בצורה יותר מתוחכמת, שכרגע אני לא מסוגל לחשוב עליה? תודה
 

עידו פ

New member
אפשר כך ואפשר אחרת

Factory method אכן יותר מתאים למשהו hard coded, כי כל מחלקה שיורשת ומממשת את ה-factory method יודעת מה היא צריכה ליצור. בשיטה זו לרוב ההחלטה היא איזה אובייקט ליצור ולא איזה אובייקט לאתחל בתוך ה-factory method (לדוגמה - המסך יחליט איזה פקד להציג עפ"י איזשהי לוגיקה, הפקד עצמו יכיל מתודת factory קבועה שתאתחל אותו). במקרה של abstract factory המקרה קצת שונה כי זה תלוי במצב. הרבה אנשים שמעצבים factory שכזה לרוב מתחילים ממצב שיש רצון למימוש שונה אבל עדין אין מימושים שונים, ולכן מה שנוצר זה abstract factory שיוצר instance בצורה hard-coded כפי שהדגמת. כאשר מגיעים למצב שאכן יש כמה מחלקות שניתן ליצור ב-abstract אפשר לעשות את זה hard coded (תנאי if/else) או בשיטות יותר דינמיות (כגון reflection/rtti וכדומה).
 

ייוניי

New member
קביעת ה factory המתאים

צריכה להעשות במקום שבו אתה יודע מהו ה factory המתאים. אם ניקח את הדוגמא של CLinuxWidgetFactory אתה אמור ליצור אותו בקטע הקוד שבו אתה יודע מהי מערכת ההפעלה שעליה רצה התוכנה. שאר הקוד שמשתמש ב CFactory כבר לא צריך לדעת... לא כל כך ברור לי למה הצורה הזו נאיבית? זו הצורה המקובלת.
 

user214

New member
מה שמפריע לי בשיטה הזאת

הוא שההחלטה, מהו ה-factory הדרוש, יושבת בתוך הקוד. נניח, שהמערכת נבנתה עבור סביבת Windows. כאשר נרצה לבצע porting לסביבת Linux, בשיטה הזאת נצטרך לפתוח את אותו קובץ הקוד ולשנות את הקוד, כלומר להחליף את CWindowsWidgetFactory ב - CLinuxWidgetFactory בקובץ הקוד עצמו. עצם ההתעסקות עם קובץ הקוד בזמן העברה למערכת אחרת נראית לי כלא ממש אלגנטית :) ובודאי קיים פתרון יותר אלגנטי. ע"י הגדרת factory לקחנו את הבעייה, איך ליצור את הפקד ופתרנו אותה. כעת factory ייצר את הפקד. אמנם נוספה בעייה אחרת: איזה פקד ליצור. זה נראה הגיוני ונכון, שההחלטה, איזה factory יוגדר, תתקבל באותו מקום בו מתקבלת ההחלטה לגבי הפלטפורמה עליה רצים. האם ה - factory pattern משאיר את הבעייה שציינתי?
 

ייוניי

New member
השאלה היא

מתי יש לך אפשרות לקבל את ההחלטה? אם יש לך דרך לבצע בדיקה של מערכת ההפעלה בזמן ריצה אז אתה יכול בזמן ריצה להחליף את ה factory בהתאם לבדיקה וכך המערכת שלך מגמישה את עצמה למערכת ההפעלה בלי נגיעה בקוד ובלי לקמפל מחדש. (עניין של להוסיף משפט תנאי מתאים שיוצר אובייקט factory מהמחלקה המתאימה). אם אין לך דרך לבצע בדיקה כזו אלא רק לשלוח קבצי הפעלה מותאמים למערכת ההפעלה של הלקוח אז ברור שהשינוי צריך להתבצע בקוד לפני קומפילציה וגם כאן יש ברוב המקרים פתרונות פרה-קומפילציה שיכולים לעזור לך. למשל, אתה יכול לשים דגל שניתן לשנות לפני כל build שיגרום ל factory המתאים להופיע בקוד ולאחרים לא להופיע. אני נותן תשובה קצת כללית כי חסר פרטים ספציפיים לבעיה אבל ברור שהפתרון צריך להיות אוטומטי ולא ידני, וברור שעדיף לדחות את ההחלטה לזמן ריצה אם אפשר.
 

arnonrgo

New member
Dependency Injection

שימוש בfactory כמו שציינת רק מעביר את הdependeny לfactory אתה יכול לקרוא את המאמר הבא של martin fowler http://www.martinfowler.com/articles/injection.html ו/או שקפים 24-35 במצגת שלי על עקרונות OO (http://www.rgoarchitects.com/Files/ooprimer.ppt) ארנון
 
למעלה