Creational Patterns: Prototype, Factory Method, and Singleton
الانماط الانشئية : وهي انماط تهدف الى فصل النظام عن كيفية انشاء وخلق ال Objects المكونة له فهي تزيد من مرونة النظام
Prototype Pattern
هذا النمط ينشئ الكائنات Objects الجديدة عن طريق الوراثة من prototypes مخزنة من قبل وميزة هذه ال prototypes انها تقوم بتسريع عملية الإنشاء.
IPrototype: تعريف الإنترفيس الذي يورث منه لنسخ ال prototypes
Prototype: الكلاس التي تحوي امكانية النسخ
PrototypeManager: يحفظ بها قائمة بانواع النسخ ومفاتيحها
Client: اضافة prototypes للقائمة وطلبات النسخ
اولا نوضح معنى كلمة النسخ لل objects : النسخ ثلاثة انواع
الطريقة الاولى : اما ان نصنع 2 refrences لمحتوى واحد في الذاكرة
مثال:
Car car1= new Car();
Car car2= car1;
هذه اول طرق النسخ وهي طريقة سطحية اذا قمت بتغيير اي شئ في car1 سوف تتغير في car2
مثلا اذا قلنا
car1.name=”BMW”;
الان لو قمنا بطباعة car2.name سنجدها = BMW
الطريقة الثانية: اننا نصنع 2 refrences وكل ريفرنس يشير الى قيمة خاصة به في الذاكرة للاوبجيكت الاول بجميع متغيراته ولكن هذه الطريقة لا تنسخ قيم الobjects الداخلة في تكوين الاوبجيكت الاول ولكن تنسخ ال refrences لها وهي عن طريق الدالة MemberwiseClone
الطريقة الثالثة: وهي نسخ العنصر كامل مهما احتوى هذه العنصر من Objects بداخله
نستعرض مثالا لكي تتضح الفكرة:
في البداية سوف ننشأ abstract كلاس لكي نرث منها ونصنع نماذج نعمل عليها
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
// Serialization is used for the deep copy option
// The type T must be marked with the attribute [Serializable( )]
[Serializable()]
public abstract class IPrototype
{
// Shallow copy
public T Clone()
{
return (T)this.MemberwiseClone();
}
// Deep Copy
public T DeepCopy()
{
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
stream.Seek(0, SeekOrigin.Begin);
T copy = (T)formatter.Deserialize(stream);
stream.Close();
return copy;
}
}
كما هو موضوح في الكومنت اننا لكي نقوم بعمليه النسخ الكامل لابد من استخدام الـ serialization
و العنصر T هو تمثيل لاي نوع Type نريد العمل عليه
وكما نرى ان الكلاس بها دالتين الاولى تقوم بعمليه نسخ سطحي للعنصر والثانية نسخ كامل للعنصر DeepCopy
استعرضنا في المثال الطريقة الثانية والثالثة للنسخ فكما Colne هي دالة تقوم على نسخ العنصر بجميع متغيراته ولكن لا تنسخ الاوبجيكت بداخله وانما تنسخ فقط ال refrence له
اما الدالة الثانية DeepCopy فهي تقوم على نسخ العنصر كامل وبذلك عند عمل اي تغيير في العنصر المنسوخ منه لا يتاثر العنصر المنسوخ نقوم بالتجربة الان لنرى الفرق
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using PrototypePattern;
using DP_ProtoTypes;
// Prototype Pattern Judith Bishop Dec 2006, Nov 2007
// Serializable is used for the deep copy option
[Serializable()]
// Helper class used to create a second level data structure
class DeeperData
{
public string Data { get; set; }
public DeeperData(string s)
{
Data = s;
}
public override string ToString()
{
return Data;
}
}
[Serializable()]
class Prototype : IPrototype<Prototype>
{
// Content members
public string Country { get; set; }
public string Capital { get; set; }
public DeeperData Language { get; set; }
public Prototype(string country, string capital, string language)
{
Country = country;
Capital = capital;
Language = new DeeperData(language);
}
public override string ToString()
{
return Country + "\t\t" + Capital + "\t\t->" + Language;
}
}
[Serializable()]
class PrototypeManager : IPrototype<Prototype>
{
public Dictionary<string, Prototype> prototypes = new Dictionary<string, Prototype> {
{"Germany", new Prototype ("Germany", "Berlin", "German")}, {"Italy", new Prototype ("Italy", "Rome", "Italian")}, {"Australia", new Prototype ("Australia", "Canberra", "English")} };
}
class PrototypeClient : IPrototype<Prototype>
{
static void Report(string s, Prototype a, Prototype b)
{
Console.WriteLine("\n" + s);
Console.WriteLine("Prototype " + a + "\nClone " + b);
}
static void Main()
{
PrototypeManager manager = new PrototypeManager();
Prototype c2, c3;
// Make a copy of Australia's data
c2 = manager.prototypes["Australia"].Clone();
Report("Shallow cloning Australia\n===============",
manager.prototypes["Australia"], c2);
// Change the capital of Australia to Sydney
c2.Capital = "Sydney";
Report("Altered Clone's shallow state, prototype unaffected",
manager.prototypes["Australia"], c2);
// Change the language of Australia (deep data)
c2.Language.Data = "Chinese";
Report("Altering Clone deep state: prototype affected *****",
manager.prototypes["Australia"], c2);
Console.WriteLine("\n====================================================================");
// Make a copy of Germany's data
c3 = manager.prototypes["Germany"].DeepCopy();
Report("Deep cloning Germany\n============",
manager.prototypes["Germany"], c3);
// Change the capital of Germany
c3.Capital = "Munich";
Report("Altering Clone shallow state, prototype unaffected",
manager.prototypes["Germany"], c3);
// Change the language of Germany (deep data)
c3.Language.Data = "Turkish";
Report("Altering Clone deep state, prototype unaffected",
manager.prototypes["Germany"], c3);
}
}
قمنا الان بعمل كلاس Prototype لتكون هيه العنصر الذي نقوم بنسخه وقمنا ايضا بعمل كلاس Data لتكون داخل هذا العنصر لنرى مدى التغيير الطارئ عليها عند عمل نسخة بكلا الدالتين
وتكون النتيجة كالتالي
Shallow cloning Australia
===============
Prototype Australia Canberra ->English
Clone Australia Canberra ->English
Altered Clone's shallow state, prototype unaffected
Prototype Australia Canberra ->English
Clone Australia Sydney ->English
Altering Clone deep state: prototype affected *****
Prototype Australia Canberra ->Chinese
Clone Australia Sydney ->Chinese
=======================================================================
Deep cloning Germany
============
Prototype Germany Berlin ->German
Clone Germany Berlin ->German
Altering Clone shallow state, prototype unaffected
Prototype Germany Berlin ->German
Clone Germany Munich ->German
Altering Clone deep state, prototype unaffected
Prototype Germany Berlin ->German
Clone Germany Munich ->Turkish
so bad
ردحذف