תבנית Factory Method

שיטת המפעל ב-[[UML]]
בתחום הנדסת התוכנה, תבנית Factory Method (שיטת המפעל) היא תבנית עיצוב שתכליתה יצירת אובייקטים החולקים ממשק אחיד מבלי להכיר את המחלקות שלהם. התבנית מתבססת על הגדרת שיטה עצמאית ליצירת עצמים. מחלקות שיורשות יכולות לדרוס את השיטה בשיטה משלהן וכך ניתן לציין את הטיפוס המפורש המתבקש.

מהות תבנית המפעל היא להגדיר ממשק ליצירת עצם תוך מתן האפשרות לתת-המחלקות המממשות את הממשק להחליט לאיזה מחלקה ליצור מופע. יצירת המופע נדחית לתת המחלקות. מקובל להשתמש בתבנית ב-Toolkit וב-Framework שם הקוד צריך לייצר עצמים מסוגים שונים אשר עשויים להיות נורשים על ידי אפליקציות אחרות. כן נעשה שימוש בתבנית כאשר עצמים מהיררכיה אחת נדרשים ליצור אובייקטים מתאימים מהיררכיה אחרת.

פונקציות מפעל מבצעות כימוס (אנקפסולציה) ליצירת עצמים. הדבר שימושי כאשר תהליך היצירה של מחלקה מורכב ותלוי בהרבה גורמים למשל בגורמי תצורה או קונפיגורציה של האפליקציה או בקלט משתמש.

==דוגמה==
בדוגמה הבאה הפונקציה MazeGame היא פונקציית תבנית המתארת משחק ועושה שימוש ב-Factory Method בשם makeRoom ליצירת חדרים במשחק (בניגוד לצורה הרגילה ליצירת אובייקט של חדר - בעזרת האופרטור new), ובצורה זו לא מכירה את הסוג הספציפי שלהם:
<syntaxhighlight lang="java">

public class MazeGame {
 public MazeGame() {
 Room room1 = makeRoom();
 Room room2 = makeRoom();
 room1.connect(room2);
 this.addRoom(room1);
 this.addRoom(room2);
 }

 protected Room makeRoom() {
 return new OrdinaryRoom();
 }
}
</syntaxhighlight>

במימוש של משחק שונה של MazeGame (ושיורש ממנו) ניתן לעשות שימוש בMazeGame זהה, אך לדרוס את פונקציית makeRoom ולקבל סוג חדר אחר:
<syntaxhighlight lang="Java">
public class MagicMazeGame extends MazeGame {
 @Override
 protected Room makeRoom() {
 return new MagicRoom();
 }
}
</syntaxhighlight>

==מגבלות==
קיימות מספר מגבלות אשר קשורות לשימוש במתודת מפעל ובהן:

* שכתוב של מחלקה כך שתיבנה באמצעות Factory Method מפירה את החוזה עם לקוחות המחלקה. למשל אם המחלקה Complex הייתה מחלקה רגילה אז היו לה וודאי לקוחות רבים המאתחלים אותה כך : <syntaxhighlight lang="java">Complex c = new Complex(-1, 0);</syntaxhighlight> ברגע שמכירים בכך ששתי מחלקות מפעל שונות נחוצות משנים את קוד המחלקה לקוד שהודגם קודם אולם כעת הבנאי הוא private ולכן הקוד של הלקוח אינו עובר הידור.

* מאחר שהתבנית מתבססת על שימוש בבנאי private המחלקה לא יכולה להיות מורחבת.
* כשמרחיבים את המחלקה (כאשר הופכים את מתודה הבנאי ל-protected) אז תת-המחלקות חייבות לספק את המימוש שלהן לכל מתודות המפעל.

==שימושים==

*ב-ADO.NET, [http://msdn2.microsoft.com/en-us/library/system.data.idbcommand.createparameter.aspx IDbCommand.CreateParameter] הוא דוגמה לשימוש בתבנית עיצוב זו.
*ב-Qt, [http://qt-project.org/doc/qt-4.8/qmainwindow.html#createPopupMenu QMainWindow::createPopupMenu] היא שיטה המשתמשת בתבנית עיצוב זו המוגדרת בתשתית שניתן לרמוס בקוד האפליקציה.
* ב-Java, יש שימוש בתבנית עיצוב זו מספר פעמים במארז (package) [https://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/package-summary.html javax.xml.parsers] . דוגמאות לכך הם javax.xml.parsers.DocumentBuilderFactory או javax.xml.parsers.SAXParserFactory.

== לקריאה נוספת ==
<div class="mw-content-ltr">
*
*
*
</div>

==קישורים חיצוניים==
*מימוש של [https://web.archive.org/web/20180110103637/http://designpattern.co.il/Factory.html Factory Pattern] ב Java
*מימוש והסבר פרקטי על [https://web.archive.org/web/20181024192103/http://bugless.co/factory-pattern-part-a/ Factory Pattern] ב #C (עברית)
*[https://web.archive.org/web/20080503082912/http://www.lepus.org.uk/ref/companion/FactoryMethod.xml Factory method in UML and in LePUS3] (a Design Description Language)
*[http://c2.com/cgi/wiki?FactoryMethodPattern Description from the Portland Pattern Repository]

Factory Method