بحث هذه المدونة الإلكترونية

السبت، 19 يونيو 2010

Creational Patterns - Prototype Pattern

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

هناك تعليق واحد: