תבנית Prototype

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

מימוש

על מנת לממש את התבנית, נגדיר מחלקה בסיסית מופשטת אשר מכילה מתודה clone (יכולה גם להיות ממשק). כל מחלקה אשר צריכה שלמחלקת הבסיס תהיה היכולת ליצור העתק בזמן ריצה של עצמה תממש את המתודה clone.
בצד ה-Client, במקום לרשום קוד שמשתמש ב-new וכן רושם "hard-coded" את שם המחלקה, פשוט נקרא למתודה clone, אשר תיצור עבורנו את האובייקט מהטיפוס המבוקש.

Java

/** * Prototype Class */public class Cookie implements Cloneable {
 
    @Override
    public Cookie clone() {
        Cookie copy;
        try {
            copy = (Cookie) super.clone();
        } catch (CloneNotSupportedException unexpected) {
            throw new AssertionError(unexpected);
        }
 
        //In an actual implementation of this pattern you might now change references to
        //the expensive to produce parts from the copies that are held inside the prototype.
 
        return copy;
    }}/** * Concrete Prototypes to clone */public class CoconutCookie extends Cookie { }/** * Client Class */public class CookieMachine {
 
    private Cookie cookie; // Could have been a private Cloneable cookie.
 
    public CookieMachine(Cookie cookie) {
        this.cookie = cookie;
    }
 
    public Cookie makeCookie() {
        return (Cookie) cookie.clone();
    }
 
    public static void main(String args[]) {
        Cookie tempCookie = null;
        Cookie prot = new CoconutCookie();
        CookieMachine cm = new CookieMachine(prot);
        for (int i = 0; i < 100; i++)
            tempCookie = cm.makeCookie();
    }}

C#

public abstract class Cookie
    {
        protected string Color { get; set; }

        public Cookie Clone()
        {
            return (Cookie)this.MemberwiseClone();  // Create a shallow copy
        }

        public override string ToString()
        {
            return string.Format("{0} Cookie", this.Color);
        }
    }


    public class ChocolateCookie : Cookie
    {
        public ChocolateCookie()
        {
            this.Color = "Brown";
        }
    }


    public class WhiteChocolateCookie : Cookie
    {
        public WhiteChocolateCookie()
        {
            this.Color = "White";
        }
    }

    
    public class CookieMachine
    {
        private Cookie cookie;

        public CookieMachine(Cookie cookieToClone)
        {
            this.cookie = cookieToClone;
        }

        public Cookie MakeCookie()
        {
            return cookie.Clone(); 
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Cookie tempCookie = null;
            Cookie prototype = new WhiteChocolateCookie();
            CookieMachine cookieMachine = new CookieMachine(prototype);
            for (int i = 0; i < 10; i++)
                tempCookie = cookieMachine.MakeCookie();
        }
    }