Flyweight Pattern

 

Comments

 

Code

 

 

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;

public interface ICoffeeFlavourFactory {
    CoffeeFlavour GetFlavour(string flavour);
}

public class ReducedMemoryFootprint : ICoffeeFlavourFactory {
    private readonly object _cacheLock = new object();
    private readonly IDictionary _cache = new Dictionary();

    public CoffeeFlavour GetFlavour(string flavour) {
        if (_cache.ContainsKey(flavour)) return _cache[flavour];
        var coffeeFlavour = new CoffeeFlavour(flavour);
        ThreadPool.QueueUserWorkItem(AddFlavourToCache, coffeeFlavour);
        return coffeeFlavour;
    }

    private void AddFlavourToCache(object state) {
        var coffeeFlavour = (CoffeeFlavour)state;
        if (!_cache.ContainsKey(coffeeFlavour.Flavour)) {
            lock (_cacheLock) {
                if (!_cache.ContainsKey(coffeeFlavour.Flavour)) _cache.Add(coffeeFlavour.Flavour, coffeeFlavour);
            }
        }
    }
}

public class MinimumMemoryFootprint : ICoffeeFlavourFactory {
    private readonly ConcurrentDictionary _cache = new ConcurrentDictionary();

    public CoffeeFlavour GetFlavour(string flavour) {
        return _cache.GetOrAdd(flavour, flv => new CoffeeFlavour(flv));
    }
}

Simple implementation

 

Flyweight allows you to share bulky data which are common to each object. In other words, if you think that same data is repeating for every object, you can use this pattern to point to the single object and hence can easily save space. Here the FlyweightPointer creates a static member Company, which is used for every object of MyObject.

 

public class FlyWeight
{
    public string CompanyName { get; set; }
    public string CompanyLocation { get; set; }
    public string CompanyWebSite { get; set; }
    //Bulky Data
    public byte[] CompanyLogo { get; set; } 
}
public static class FlyWeightPointer
{
    public static readonly FlyWeight Company = new FlyWeight
    {
        CompanyName = "Abc",
        CompanyLocation = "XYZ",
        CompanyWebSite = "www.abc.com"
        // Load CompanyLogo here
    };
}
public class MyObject
{
    public string Name { get; set; }
    public string Company
    {
        get
        {
            return FlyWeightPointer.Company.CompanyName;
        }
    }
}


1.	                 
2.	
3.	using System;
4.	using System.Collections.Generic;
5.	 
6.	namespace DoFactory.GangOfFour.Flyweight.RealWorld
7.	{
8.	  /// 
9.	  /// MainApp startup class for Real-World 
10.	  /// Flyweight Design Pattern.
11.	  /// 
12.	  class MainApp
13.	  {
14.	    /// 
15.	    /// Entry point into console application.
16.	    /// 
17.	    static void Main()
18.	    {
19.	      // Build a document with text
20.	      string document = "AAZZBBZB";
21.	      char[] chars = document.ToCharArray();
22.	 
23.	      CharacterFactory factory = new CharacterFactory();
24.	 
25.	      // extrinsic state
26.	      int pointSize = 10;
27.	 
28.	      // For each character use a flyweight object
29.	      foreach (char c in chars)
30.	      {
31.	        pointSize++;
32.	        Character character = factory.GetCharacter(c);
33.	        character.Display(pointSize);
34.	      }
35.	 
36.	      // Wait for user
37.	      Console.ReadKey();
38.	    }
39.	  }
40.	 
41.	  /// 
42.	  /// The 'FlyweightFactory' class
43.	  /// 
44.	  class CharacterFactory
45.	  {
46.	    private Dictionary _characters =
47.	      new Dictionary();
48.	 
49.	    public Character GetCharacter(char key)
50.	    {
51.	      // Uses "lazy initialization"
52.	      Character character = null;
53.	      if (_characters.ContainsKey(key))
54.	      {
55.	        character = _characters[key];
56.	      }
57.	      else
58.	      {
59.	        switch (key)
60.	        {
61.	          case 'A': character = new CharacterA(); break;
62.	          case 'B': character = new CharacterB(); break;
63.	          //...
64.	          case 'Z': character = new CharacterZ(); break;
65.	        }
66.	        _characters.Add(key, character);
67.	      }
68.	      return character;
69.	    }
70.	  }
71.	 
72.	  /// 
73.	  /// The 'Flyweight' abstract class
74.	  /// 
75.	  abstract class Character
76.	  {
77.	    protected char symbol;
78.	    protected int width;
79.	    protected int height;
80.	    protected int ascent;
81.	    protected int descent;
82.	    protected int pointSize;
83.	 
84.	    public abstract void Display(int pointSize);
85.	  }
86.	 
87.	  /// 
88.	  /// A 'ConcreteFlyweight' class
89.	  /// 
90.	  class CharacterA : Character
91.	  {
92.	    // Constructor
93.	    public CharacterA()
94.	    {
95.	      this.symbol = 'A';
96.	      this.height = 100;
97.	      this.width = 120;
98.	      this.ascent = 70;
99.	      this.descent = 0;
100.	    }
101.	 
102.	    public override void Display(int pointSize)
103.	    {
104.	      this.pointSize = pointSize;
105.	      Console.WriteLine(this.symbol +
106.	        " (pointsize " + this.pointSize + ")");
107.	    }
108.	  }
109.	 
110.	  /// 
111.	  /// A 'ConcreteFlyweight' class
112.	  /// 
113.	  class CharacterB : Character
114.	  {
115.	    // Constructor
116.	    public CharacterB()
117.	    {
118.	      this.symbol = 'B';
119.	      this.height = 100;
120.	      this.width = 140;
121.	      this.ascent = 72;
122.	      this.descent = 0;
123.	    }
124.	 
125.	    public override void Display(int pointSize)
126.	    {
127.	      this.pointSize = pointSize;
128.	      Console.WriteLine(this.symbol +
129.	        " (pointsize " + this.pointSize + ")");
130.	    }
131.	 
132.	  }
133.	 
134.	  // ... C, D, E, etc.
135.	 
136.	  /// 
137.	  /// A 'ConcreteFlyweight' class
138.	  /// 
139.	  class CharacterZ : Character
140.	  {
141.	    // Constructor
142.	    public CharacterZ()
143.	    {
144.	      this.symbol = 'Z';
145.	      this.height = 100;
146.	      this.width = 100;
147.	      this.ascent = 68;
148.	      this.descent = 0;
149.	    }
150.	 
151.	    public override void Display(int pointSize)
152.	    {
153.	      this.pointSize = pointSize;
154.	      Console.WriteLine(this.symbol +
155.	        " (pointsize " + this.pointSize + ")");
156.	    }
157.	  }
158.	}

Output

 

A (pointsize 11)
A (pointsize 12)
Z (pointsize 13)
Z (pointsize 14)
B (pointsize 15)
B (pointsize 16)
Z (pointsize 17)
B (pointsize 18)