نموذج التصميم وزن الذبابة

من ويكيبيديا، الموسوعة الحرة
اذهب إلى: تصفح، ‏ ابحث

هذا النموذج يفيد في بعض الحالات التي نستخدم فيها كائن صغير وكثير فلستهلك كثيرا من المصادر و يكون من المفضل وقتها ان نجمع كل هذه الكائنات الصغيرة في كائن واحد كبير او اقل عدد ممكن من الكائنات الكبيرة نوعا ما هو اوفر على النظام من كائنات كثيرة صغيرة.
- هذا النموذج يقوم على تقسيم الكائنات إلى 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, null, new 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<string, IFlyweight> flyweights =new Dictionary<string, IFlyweight>();
 
        public FlyweightFactory()
        {
            flyweights.Clear();
 
        }
 
        public IFlyweight this[string index]
        {
            get
            {
                if (!flyweights.ContainsKey(index))
                    flyweights[index] = new Flyweight();
                return flyweights[index];
            }
        }
    }

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

الان نقوم بعمل الصف التي ستعرض الصور

   class Client
    {
        // Shared state - the images
        static FlyweightFactory album = new FlyweightFactory();
        // Unshared state - the groups
        static Dictionary<string, List<string>> allGroups = new Dictionary<string, List<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