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)); } }
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)