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

الاثنين، 7 يونيو 2010

Flyweight Pattern

Flyweight Pattern
هذا النمط يفيد في بعض الحالات التي نستخدم فيها objects صغيرة وكثيرة فتستهلك كثيرا من ال resources ويكون من المفضل وقتها ان نجمع كل هذه الكائنات الصغيرة في كائن واحد كبير او اقل عدد ممكن من الكائنات الكبيرة نوعا ما هو اوفر على النظام من كائنات كثيرة صغيرة
-         هذا النمط يقوم على تقسيم الكائنات الى intrinsic data و extrinsic data والجزء الاول يكون للوظائف الداخليه للكلاس ولا يمكن فصلها عن الكائن اما الجزء الثاني فهي الوظائف التي من الممكن ان تفصلها عن الكلاس وتخزن خارجه وبذلك يمكننا ان نستبدل جميع الاجزاء المتشابهه في الجزء الداخلي واستبدالها بكائن واحد
وهناك جزء اخر يدير عملية التاكد من عدم وجود الكائن قبل انشائه اي يتاكد اننا لم ننشأ intrinsic data مطابقة من قبل وفي حالة اننا انشئناها من قبل يقوم باستخدامها في انشاء الاوبجيكت الجديد بدلا من انشاء intrinsic data جديدة


Client : يدير ويعمل على ادارة الوظائف الداخلية  للكائن
IFlyweight :    انترفيس يستخدم في انشاء البيانات الداخلية للكائنات  intrinsic State
FlyweightFactory : انشاء وادارة الاجزاء الفريدة من نوعها data intrinsic
Flyweight: تخزين وانشاء ومشاركة الكائنات المتشابهة بين الكائنات
مثال : عرض صور مصغرة ومقسمة الى مجموعات
في البداية نقوم بعمل الانترفيس الذي سنشتق منه
public interface IFlyweight
    {
        void Load(string filename);
        void Display(PaintEventArgs e, int row, int col);
    }
وهي انترفيس بها العمليات الداخلية للكائن الذي نريد ان ننشأه وبها دالتين .. الاولى هي Load وهي تقوم على تحميل الصور المصغرة بالذاكرة اما الثانية فهي تقوم بعرض ورسم الصور على الشاشة

الخطوة الثانية – نقوم بعمل استركتشر يرث من الانترفيس
public struct Flyweight : IFlyweight
    {
        // Intrinsic state
        Image pThumbnail;
        public void Load(string filename)
        {

                pThumbnail = new Bitmap(@"E:\wallpapers\" + filename).GetThumbnailImage(100, 100, nullnew IntPtr());
        }

        public void Display(PaintEventArgs e, int row, int col)
        {
            e.Graphics.DrawImage(pThumbnail, col * 100 + 10, row * 130 + 40, pThumbnail.Width, pThumbnail.Height);
        }
    }

الان نملك استركتشر يقوم بعمل ادراج للصورة في الذاكرة ويقوم برسم الصورة على الواجهة
·        لاحظ ان الدالة load لا تقوم بارجاع القيمة انها فقط تقوم بعملها ولا تعيد القيمة في ال return value ثم نقوم بانشاء كلاس تعمل على تخزين الوحدات من الاستركتشر السابق



public class FlyweightFactory
    {
        // Keeps an indexed list of IFlyweight objects in existence
        Dictionary<stringIFlyweight> flyweights =new Dictionary<stringIFlyweight>();

        public FlyweightFactory()
        {
            flyweights.Clear();
           
        }


        public IFlyweight this[string index]
        {
            get
            {
                if (!flyweights.ContainsKey(index))
                    flyweights[index] = new Flyweight();
                return flyweights[index];
            }
        }
    }

كما نرى الكلاس في بدايته يقوم بتعريف Directory المفتاح فيه استرينج والقيمة FlyWeight
وبه indexer تقوم بارجاع قيمة ال flyweight  اذا وجدت والا فانه يقوم بانشاء flyweight  جديد وبذلك من خلال الكلاس نفسها نكون قادرين على الولوج الى الاوبجيكت المراد مباشرة

الان نقوم بعمل الكلاس التي ستعرض الصور
   class Client
    {
        // Shared state - the images
        static FlyweightFactory album = new FlyweightFactory();
        // Unshared state - the groups
        static Dictionary<stringList<string>> allGroups = new Dictionary<stringList<string>>();
        public void LoadGroups()
        {
            var myGroups = new[] {
new {Name = "FirstGroup",
Members = new [] {"1.jpg""2.jpg","3.jpg""4.jpg"}},
new {Name = "SecondGroup",
Members = new [] {"5.jpg","6.jpg","7.jpg""8.jpg"}},
new {Name = "ThirdGroup",
Members = new [] {"9.jpg""10.jpg"}}

};
            // Load the Flyweights, saving on shared intrinsic state
            foreach (var g in myGroups)
            { // implicit typing
                allGroups.Add(g.Name, new List<string>());
                foreach (string filename in g.Members)
                {
                    allGroups[g.Name].Add(filename);
                    album[filename].Load(filename);
                }
            }
        }

        public void DisplayGroups(Object source, PaintEventArgs e)
        {
            // Display the Flyweights, passing the unshared state
            int row = 0;
            foreach (string g in allGroups.Keys)
            {
                int col = 0;
                e.Graphics.DrawString(g, new Font("Arial", 16), new SolidBrush(Color.Black), new PointF(0, row * 130 + 10));
                foreach (string filename in allGroups[g])
                {
                    album[filename].Display(e, row, col);
                    col++;
                }
                row++;
            }
        }
    }

 كلاس client هي المسؤولة عن اخراج الصورة في شكلها النهائي  نقوم بتعريف اوبجيكت من الكلاس FlyweightFactory لكي نضع به صور كل البوم ثم نقوم بعمل مصفوفةdirectory لكي نضع بها اسماء الصور واسماء مجموعات الصور.
وضعنا دالتين في هذه الكلاس الاولى LoadGroups وهي تعمل على ادراج الصور والمجموعات في المصفوفات الخاصة بها
الدالة الثانية وهي DisplayGroup هي دالة عملها الاساسي هو القيام باستدعاء الدالة Display من كلاس FlyWieght لتقوم برسم الصورة

الان نقوم باستدعاء بتشغيل البرنامج كالاتي
public partial class Window : Form
    {

        public Window()
        {
            InitializeComponent(); 
            this.Height = 600;
            this.Width = 600;
            this.Text = "Picture Groups";
            Client client = new Client();
            client.LoadGroups();

            this.Paint+= new PaintEventHandler(client.DisplayGroups);

        }

     

        static void Main()
        {
            Application.Run(new Window());
        }

    }
كما نرى البرنامج يعمل على مراحل في البداية قمنا باستدعاء الدالة LoadGroups لكي نجمع الصور لعرضها اثناء العرض وكما نرى الحدث Paint يقوم باستدعاء الدالةDisplayGroups



ليست هناك تعليقات:

إرسال تعليق