الگوی Prototype

الگوی Prototype(نمونه اولیه) در دسته الگوهای ایجادی قرار دارد.نوع اشیاء را با استفاده از Prototype(نمونه اولیه) نمونه مشخص کنید و اشیاء جدید را با کپی کردن این Prototype ایجاد می کند.به عبارت دیگر تسریع روند نمونه سازی و ایجاد اشیا با کپی سازی از نمونه‌های از پیش موجود. UML class diagram شركت كنندگان کلاس ها و اشیاء شرکت کننده در این الگو عبارتند از:نمونه اولیه Prototype (درمثال دنیای واقعی ColorPrototype) : تعریف یک interface (واسط) برای شبیه سازی خودش.به عبارت دیگر شکل کلی همه موجودیت هایی را که می‌خواهند قابلیت کپی سازی داشته باشند تعریف می کند(اما کاری با نحوه کپی سازی ندارد). در.NET از قبل واسطی به اسم IClonable برای این کار تعریف شده است. نمونه اولیه سفت ConcretePrototype (در مثال دنیای واقعی Color) : پیاده سازی عملیات برای شبیه سازی خودش.به عبارت دیگر کلاسی است که می‌خواهد قابلیت کپی داشته باشد. این کلاس با پیاده سازی واسطه Prototype منطق لازم برای کپی سازی از نمونه هایش را تعریف می کند.کلاینت Client (در مثال دنیای واقعی ColorManager) : ساخت یک شی جدید با درخواست یک نمونه اولیه برای ایجاد کلون خود.به عبارت دیگر کلاینتی است که برای به دست آوردن نمونه ی جدید از ConcretePrototype ، به جای نمونه سازی صریح از این کلاس، متد Clone() را برای نمونه ای از آن صدا میزند. برای کلاینت اهمیتی ندارد نام کلاس شی Prototype چیست.به همین دلیل تنها کافی است ارجاعی به واسط IPrototype (یا asbtrac class Prototype) در اختیار داشته باشد و نیازی نیست از ConcretePrototype خبر داشته باشد. یعنی تنها کافی است بداند و شی ایکه هم اکنون در اختیار او است متدی به اسم Clone() دارد که می تواند با فراخوانی آن، نمونه دیگری همانند آن به دست بیاورد. ساختار کلی کداین کد ساختاری الگو نشان می دهد که در آن اشیاء جدید با کپی کردن اشیاء (اشیاء prototypes) موجود از همان کلاس ایجاد می شوند. using System; namespace DoFactory.GangOfFour.Prototype.Structural { /// <summary> /// MainApp startup class for Structural /// Prototype Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main () { // Create two instances and clone each ConcretePrototype1 p1 = new ConcretePrototype1 ("I"); ConcretePrototype1 c1 = (ConcretePrototype1) p1.Clone (); Console.WriteLine ("Cloned: {0}", c1.Id); ConcretePrototype2 p2 = new ConcretePrototype2 ("II"); ConcretePrototype2 c2 = (ConcretePrototype2) p2.Clone (); Console.WriteLine ("Cloned: {0}", c2.Id); // Wait for user Console.ReadKey (); } } /// <summary> /// The 'Prototype' abstract class /// </summary> abstract class Prototype { private string _id; // Constructor public Prototype (string id) { this._id = id; } // Gets id public string Id { get { return _id; } } public abstract Prototype Clone (); } /// <summary> /// A 'ConcretePrototype' class /// </summary> class ConcretePrototype1 : Prototype { // Constructor public ConcretePrototype1 (string id) : base (id) { } // Returns a shallow copy public override Prototype Clone () { return (Prototype) this.MemberwiseClone (); } } /// <summary> /// A 'ConcretePrototype' class /// </summary> class ConcretePrototype2 : Prototype { // Constructor public ConcretePrototype2 (string id) : base (id) { } // Returns a shallow copy public override Prototype Clone () { return (Prototype) this.MemberwiseClone (); } } } OutputCloned : ICloned : IIیاpublic interface IPrototype { IPrototype Clone(); } public class ConcretePrototype: IPrototype { public int SomeProperty { get; set; } public ConcretePrototype(int someProperty) { this.SomeProperty = someProperty; } public IPrototype Clone() { return (IPrototype)this.MemberwiseClone(); } } public class ComplexClass: IPrototype { public ConcretePrototype SomeProperty { get; set; } public ComplexClass(ConcretePrototype someProperty) { this.SomeProperty = someProperty; } public IPrototype Clone() { var result = (ComplexClass)this.MemberwiseClone(); result.SomeProperty = (ConcretePrototype)this.SomeProperty.Clone(); return (IPrototype)result; } } public class Test { public static void Main() { ConcretePrototype cp1 = new ConcretePrototype(25); ConcretePrototype cp2 = (ConcretePrototype)cp1.Clone(); Console.WriteLine("cp1.SomeProperty == cp2.SomeProperty? {0}", (cp1.SomeProperty == cp2.SomeProperty)); Console.WriteLine("cp1 == cp2? {0}", (cp1 == cp2)); Console.WriteLine(); ComplexClass cc1 = new ComplexClass(cp1); ComplexClass cc2 = (ComplexClass)cc1.Clone(); Console.WriteLine("cc1.SomeProperty == cc2.SomeProperty? {0}", (cc1.SomeProperty == cc2.SomeProperty)); Console.WriteLine("cc1 == cp2? {0}", (cc1 == cc2)); Console.ReadKey(); } } /* Outputcp1.SomeProperty == cp2.SomeProperty? Truecp1 == cp2? Falsecc1.SomeProperty == cc2.SomeProperty? Falsecc1 == cp2? False*/کد دنیای واقعیاین کد نشان می دهد که در آن اشیای رنگی جدید با کپی کردن رنگ های موجود از قبل تعریف شده توسط کاربر از همان نوع ایجاد می شوند. using System; using System.Collections.Generic; namespace DoFactory.GangOfFour.Prototype.RealWorld { /// <summary> /// MainApp startup class for Real-World /// Prototype Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main () { ColorManager colormanager = new ColorManager (); // Initialize with standard colors colormanager["red"] = new Color (255, 0, 0); colormanager["green"] = new Color (0, 255, 0); colormanager["blue"] = new Color (0, 0, 255); // User adds personalized colors colormanager["angry"] = new Color (255, 54, 0); colormanager["peace"] = new Color (128, 211, 128); colormanager["flame"] = new Color (211, 34, 20); // User clones selected colors Color color1 = colormanager["red"].Clone () as Color; Color color2 = colormanager["peace"].Clone () as Color; Color color3 = colormanager["flame"].Clone () as Color; // Wait for user Console.ReadKey (); } } /// <summary> /// The 'Prototype' abstract class /// </summary> abstract class ColorPrototype { public abstract ColorPrototype Clone (); } /// <summary> /// The 'ConcretePrototype' class /// </summary> class Color : ColorPrototype { private int _red; private int _green; private int _blue; // Constructor public Color (int red, int green, int blue) { this._red = red; this._green = green; this._blue = blue; } // Create a shallow copy public override ColorPrototype Clone () { Console.WriteLine ( "Cloning color RGB: {0,3},{1,3},{2,3}", _red, _green, _blue); return this.MemberwiseClone () as ColorPrototype; } } /// <summary> /// Prototype manager /// </summary> class ColorManager { private Dictionary<string, ColorPrototype> _colors = new Dictionary<string, ColorPrototype> (); // Indexer public ColorPrototype this [string key] { get { return _colors[key]; } set { _colors.Add (key, value); } } } } OutputCloning color RGB : 255, 0, 0Cloning color RGB : 128, 211, 128Cloning color RGB : 211, 34, 20