Flyweight Design Pattern

Flyweight tasarım deseni

Selam dostlar!

Flyweight Design Pattern ile yolculuğumuza devam ediyoruz.

Diğer tasarım desenlerinde yaptığımız gibi önce problemi ele alarak başlayalım. Bir uygulamanın arayüzünü geliştirirken, aynı veriyi farklı biçimlerde sunmak isteriz. Burada hedeflerden biri, son kullanıcının görsel ihtiyacını tatmin etmektir elbette. Ancak işin bir de performans kısmı var. Hadi örneğimizi biraz daha detaylandıralım. Bir masaüstü uygulaması geliştirdiğinizi düşünelim. Bu uygulamada kullanıcı, ürün kartlarının nasıl görüneceğini kendisi belirlemek istiyor. Bu noktada her bir ürünün bir fotoğrafı olduğunu da hesaba katalım. Ürün kartının gösterim biçimi her değiştiğinde, ilgili fotoğrafın tekrar tekrar işlemden geçmesi ne kadar mantıklı? Her bir fotoğrafı, her seferinde veritabanından (ya da dosyadan) okumak yerine belleğe atmayı tercih ederiz sanırım. Bu sayede bellek performansını oldukça büyük oranlarda arttırmak mümkün olabilir.

Yani her fotoğrafı yalnızca bir kere kaynağından okuyup ardından belleğe kaydetmeliyim. Böylelikle daha sonra her ihtiyaç duyduğumda tekrar bellekten okuyabilirim. Bu bana, fotoğrafı ürün kartında dilediğim kombinasyonda kullanma şansı verecektir.

Bakın, bu aklıma bir örnek daha getirdi. Biraz daha eğlenceli bir şey düşünelim. Sadece birkaç ağaç türünden bir orman görüntüsü yaratmak istiyorsunuz. Yani kullanıcı; çam, kavak ya da huş ağacı gibi birkaç tane ağaç seçecek ve toplam kaç ağaç olması istediğini belirleyecek. Sizin göreviniz, bu ağaç türlerinin fotoğrtaflarını rastgele bir araya getirerek bir orman görüntüsü oluşturmak. Nasıl hareket edersiniz?

Eğer; kullanıcının seçtiği ağaç fotoğraflarından birer tane bellekte yaratırım sonra da bunları rastgele seçerek, rastgele noktalara yerleştiririm diyorsanız tebrikler! Flyweight desenini ortaya attınız işte!

Hadi o zaman! Sıra kod örneğinde… Senaryomuz da, belirli renklerden oluşan, toplam sayısını kullanıcının belirlediği balonları rastgele noktalara çizmek olsun. Renkler belirli olduğuna göre, Balon sınıfının constructor’ında renk bilgisini alabilirim. O zaman Balon sınıfımız aşağıdaki gibi olmalı:

 public class Balon
    {
        public Brush Color { get; set; }
        public int X { get; set; }
        public int Y { get; set; }
        public int Cap { get; set; }
        public Balon(Color color)
        {
            SolidBrush solidBrush = new SolidBrush(color);
            this.Color = solidBrush;
        }
        public void Ciz(Graphics grafik)
        {
            grafik.FillEllipse(Color, X, Y, Cap, Cap);
        }
    }

 

Şimdi, diyelim ki kırmızı, mavi ve yeşil renkli balonlardan binlercesini çizme ihtimalim var. Demek ki ilk etapta üç farklı renkten de birer adet balonu oluşturup belleğe kaydedeceğiz. Sonra da söz konusu balonu bellekten okuyup koordinatlarını değiştirmek yeterli olacak.

Belleğe kaydetme noktasında her renge bir balon düştüğüne göre, bu iş için generic Dictionary sınıfını kullanabilirim demektir. “Eğer istenen renkte balon dictionary içinde varsa doğrudan onu kullan, YOKSA oluştur ve kaydet” yaklaşımı hiç de fena olmaz sanırım. Ayrıca, bellekteki balonlara sürekli erişebilmem gerektiği için, static bir sınıf işimizi çok daha kolaylaştıracaktır.

 public static  class FlyweightBalonOlusturucu
    {
        private static Dictionary<Color, Balon> balonlar = new Dictionary<Color, Balon>();
        public static Balon BalonYarat(Color renk)
        {         
            if (!balonlar.ContainsKey(renk))
            {
                Balon baloon = new Balon(renk);
                balonlar.Add(renk,baloon);
            }
            return balonlar[renk];
        }        
    }

 

 Tamamdır. Bu arada ben bu örneği, klasik Windows Forms teması üzerinde gerçekleştiriyorum. Aşağıdaki resimdeki gibi bir arayüzüm var. Yalnız, Dock özelliği Fill olan ve arkaplanı siyah bir panel kullandığımı belirtmeliyim.



Kullanıcı, numericUpDownBalonSayisi isimli numericUpDown kontrolüne kaç adet balon istediğini belirtir ve butona tıklar.

Yani:

 private void buttonBalonEkle_Click(object sender, EventArgs e)
        {
            BalonlariOlustur(panel1.CreateGraphics(), numericUpDownBalonSayisi.Value);
        }

        private void BalonlariOlustur(Graphics grafik, decimal value)
        {
            var renkler = new string[]{ "red", "blue", "green" };

            Random random = new Random();           
            for (int i = 1; i <= value; i++)
            {                
                string rastgeleRenk = renkler[random.Next(0, renkler.Length)];
                Color renk = Color.FromName(rastgeleRenk);
                Balon balon = FlyweightBalonOlusturucu.BalonYarat(renk);
                balon.Cap = random.Next(5, 20);
                balon.X = random.Next(panel1.Width - balon.Cap);
                balon.Y = random.Next(panel1.Height - balon.Cap);
                balon.Ciz(panel1.CreateGraphics());
            }
        }

Ve tabii ki sonuç:


Sevgili dostlar. Dikkatlarden kaçmaması için bir kez daha dikkat çekmek isterim. Uygulamamız ilk etapta kırmızı, mavi ve yeşil renkli balon nesnelerini oluşturup belleğe kaydediyor. Daha sonra bunların içinden rastegele bir balon nesnesini alıp, lokasyon ve çap değerlerini değiştirip panele çizdiriyor.

Şimdi, eğer bu köşeyi takip ediyorsanız; Flyweight design pattern daha önce ele aldığım tasarım desenlerinden birine çok benzetmiş olabilirsiniz. Prototype deseninden bahsediyorum. Orada da problemi şu cümleler ile tanımlamışız:”
Üretilip belleğe aktarılması zaman açısından maliyetli olan bir nesne olduğunu varsayalım ayrıca uygulamanızda, bu nesneden birkaç tane olacağını düşünelim…”

Fark ne? Görebildiniz mi? Prototype deseni, nesneyi yaratırken karşımıza çıkan problemi çözüyor. Flyweight design pattern ise zaten oluşturulmuş nesneleri belleğe aktarıyor! Yani hali hazırda bellekte olan nesnelerin bir kombinasyonunu oluşturuyorsunuz. Sonuç olarak birbirlerine benzemelerine karşın, pratikte oldukça farklı iki işleve sahip desenlerden bahsediyoruz.

Bu noktada da, söz konusu tasarım deseninin de icabına bakmış oluyoruz.

Diğer tasarım desenleri için takipte kalın efenim…

2 thoughts on “Flyweight Design Pattern

Leave a Reply