Click here to Skip to main content
15,891,943 members
Articles / Programming Languages / C#

Flyweight Design Pattern

Rate me:
Please Sign up or sign in to vote.
4.60/5 (4 votes)
11 Aug 2015CPOL4 min read 18.4K   148   3   7
Flyweight pattern is about creating a pool of objects which allow sharing already created objects and causing applications to consume less memory.

Flyweight design pattern is one of the structural patterns introduced by GOF. Flyweight pattern is about creating a pool of objects which allow sharing already created objects and causing applications to consume less memory.

So this pattern does two things, because the pattern creates objects only once and then saves it to pool

  1. Increase application performance in terms of object creation, as there is no requirement of creating an object at every request.
  2. Cause applications to consume less memory as created objects are already in memory and no new objected because of pool.

Ultimately flyweight patterns make applications efficient in terms of memory and processing.

Basic UML class Diagram of Design Pattern

The below image shows the class diagram of basic flyweight design pattern:

Image 1

IFlyweight - Basic contract that need to be implemented by derived types i.e. by concreate flyweight.

FlyweightFactory – It’s a factory class which is used by Client class to get data from the concreate flyweight. This class is also responsible for creating a pool of already created objects. So when a request comes for data that is already requested, it returns data from pool.

ConcerateSharedFlyweight1 – It’s a concreate implementation of flyweight interface. As the name suggests, objects returned by this class are going to be shared between clients of it.

ConcerateUnSharedFlyweight1 – It’s a concreate implementation of flyweight interface. As the name suggests, objects returned by this class are going to be unshared, which means every time client requires a new object.

Client – make use of the concreate implementation, it creates an instance of Decorate and uses a functionality of it.

Note:

UnSharedFlyweight is not always required it depends on requirement, but SharedFlyweight is always required when you go for flyweight pattern.

The code below is implementation of the Flyweight design pattern and Class diagram discussed above.

C#
namespace BasicFlyweightPattern
{
    #region basic implementation
    public class FlyweightFactory
    {
        public static List<Item> GetStaticItemList(string key)
        {
            IFlyWeight flyWeight = null;
            ICacheManager _objCacheManager = CacheFactory.GetCacheManager();
 
            if (key == "A")
            {
                if (_objCacheManager.Contains("A"))
                {
                    return _objCacheManager["A"] as List<Item>;
                }
                else
                {
                    flyWeight = new ConcerateSharedFlyweight1();
                }
            }
            else if (key == "B")
            {
                if (_objCacheManager.Contains("B"))
                {
                    return _objCacheManager["B"] as List<Item>;
                }
                else
                {
                    flyWeight = new ConcerateSharedFlyweight2();
                }
            }
 
            var list = flyWeight.GetList();
            _objCacheManager.Add(key, list);
            return list;
        }
    }
 
    interface IFlyWeight
    {
        List<Item> GetList();
    }
 
    public class Item
    {
        public int id { get; set; }
        public string desc { get; set; }
    }
 
    public class ConcerateSharedFlyweight1 : IFlyWeight
    {
        private List<Item> ItemList;
 
        public ConcerateSharedFlyweight1()
        {
            ItemList = new List<Item>();
        }
 
        public List<Item> GetList()
        {
            ItemList.Add(new Item { id = 1, desc = "A1" });
            ItemList.Add(new Item { id = 2, desc = "A2" });
            ItemList.Add(new Item { id = 3, desc = "A3" });
            return ItemList;
        }
    }
 
    public class ConcerateSharedFlyweight2 : IFlyWeight
    {
        private List<Item> ItemList;
 
        public ConcerateSharedFlyweight2()
        {
            ItemList = new List<Item>();
        }
 
        public List<Item> GetList()
        {
            ItemList.Add(new Item { id = 1, desc = "B1" });
            ItemList.Add(new Item { id = 2, desc = "B2" });
            ItemList.Add(new Item { id = 3, desc = "B3" });
            return ItemList;
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            List<Item> list =FlyweightFactory.GetStaticItemList("A");
     //List<Item> list = FlyweightFactory.GetStaticItemList("B");           
     foreach (var item in list)
            {
                Console.WriteLine(item.id.ToString() + "  " + item.desc );
           }
 
            Console.ReadLine();
        }
    }
 
}

Points to remember in above code implementation

  1. Client asks for data from FlyweightFactory by calling GetStaticItemList and passing key as argument for getting data.
  2. FlyweightFactory has static method GetStaticItemList, which creates instances of concreate and get data if request comes first time, for later request it returns existing created object.
  3. FlyweightFactory maintains pool of already created objects by making use of Enterprise library. Caching block for sharing data between different clients i.e. different objects.
  4. In Concreate implementation of flyweight, a hardcoded list is returned but in actual scenarios this will be replaced by getting data from datasource.
  5. Item is a class that is poco class, list of which returned from flyweight concreate classes. This class represented by different items. The below scenario provides more detail.

Output

Image 2

Here in output shows result of A’s same will go for result of B’s. If call comes second time than data get retuned from cache.

Flyweight Design Pattern Example In RealTime Application

Problem Statement

Web Application having dropdown for displaying list of Country, displaying list of State, displaying list of Product etc. in dropdown and this dropdowns are part of multiple screen which access by multiple users.

In this scenario to display a different kind of list for multiple user request, the server needs to connect with the database server multiple items this reduce performance of application and also consumes memory for creating and storing these lists.

Solution

Solution to above problem solution is making use of Flyweight design pattern.

Below is a class diagram of Flyweight pattern used in application.

Image 3

Mapping with Basic Implementation

IFlyweightManager is equals to IFlyweight

StaticDataListFlyweightFactory is equal to FlyweightFactory.

CountryStaticListManager & ProductStaticListManager is equal to ConcerateSharedFlyweight1 & ConcerateSharedFlyweight2.

StaticItem is equal to Item.

C#
namespace FlyWeightPattern
{
    class Program
    {
        static void Main(string[] args)
        {

            List<StaticItem> countrylist = StaticDataListFlyWeidhtFactory.GetStaticItemList("Country");
            foreach (var item in countrylist)
            {
                Console.WriteLine(item.id.ToString() + "  " + item.Code + "  " + item.Description);
            }

            Console.ReadLine();
        }
    }
 public class StaticDataListFlyWeidhtFactory
    {
        public static List<StaticItem> GetStaticItemList(string key)
        {
            IFlyWeightManager manager = null;
            ICacheManager _objCacheManager = CacheFactory.GetCacheManager();

            if (key == "Country")
            {
                if (_objCacheManager.Contains("Country"))
                {
                    return _objCacheManager["Country"] as List<StaticItem>;
                }
                else
                {
                    manager = new CountryStaticListManager();
                }
            }
            else if (key == "ProductType")
            {
                if (_objCacheManager.Contains("ProductType"))
                {
                    return _objCacheManager["ProductType"] as List<StaticItem>;
                }
                else
                {
                    manager = new ProductTypeStaticListManager();
                }
            }

            var list = manager.GetList();
            _objCacheManager.Add(key, list);
            return list;
        }
    }

    interface IFlyWeightManager
    {
        List<StaticItem> GetList();
    }

    public class CountryStaticListManager : IFlyWeightManager
    {
        private List<StaticItem> StaticItemList;

        public CountryStaticListManager()
        {
            StaticItemList = new List<StaticItem>();
        }

        public List<StaticItem> GetList()
        {
            StaticItemList.Add(new StaticItem { id = 1, Code = "IND", Description = "India" });
            StaticItemList.Add(new StaticItem { id = 2, Code = "SRL", Description = "Sri Lanka" });
            StaticItemList.Add(new StaticItem { id = 3, Code = "SA", Description = "South Africa" });
            return StaticItemList;
        }
    }

    public class ProductTypeStaticListManager : IFlyWeightManager
    {
        private List<StaticItem> StaticItemList;

        public ProductTypeStaticListManager()
        {
            StaticItemList = new List<StaticItem>();
        }

        public List<StaticItem> GetList()
        {
            StaticItemList.Add(new StaticItem { id = 1, Code = "0123", Description = "Watch" });
            StaticItemList.Add(new StaticItem { id = 2, Code = "0234", Description = "Shoes" });
            StaticItemList.Add(new StaticItem { id = 3, Code = "0345", Description = "" });
            return StaticItemList;
        }
    }

    public class StaticItem
    {
        public int id { get; set; }
        public string Code { get; set; }
        public string Description { get; set; }
    }
}

Output

Image 4

So the above code works the same as already described in the Basic implementation of the pattern. In code, different types of the list get fetched by passing different keys. For this implementation, the keys are Country and Product. In a real application, one can have more than this.

The above implementation follows SOLID principle. One exception is Factory class, which needs to be modifying when one wants to add a new key so it breaks the rule of Single responsibility.

Note:

Here, country and product are listed are hardcoded, but in actuality it gets fetched from the database.

Conclusion

This pattern is very helpful in scenarios where one wants to create a pool of objects and share it between different clients (clients are software programs or classes or web applications, as in this example).

Note:

This is my point of view regarding pattern. Please provide your feedback regarding it and also provide feedback if you find something wrong.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India

Microsoft C# MVP (12-13)



Hey, I am Pranay Rana, working as a Team Leadin MNC. Web development in Asp.Net with C# and MS sql server are the experience tools that I have had for the past 5.5 years now.

For me def. of programming is : Programming is something that you do once and that get used by multiple for many years

You can visit my blog


StackOverFlow - http://stackoverflow.com/users/314488/pranay
My CV :- http://careers.stackoverflow.com/pranayamr

Awards:



Comments and Discussions

 
QuestionWhat is a ambiguous line of code! Pin
Member 1061836917-Aug-15 8:34
Member 1061836917-Aug-15 8:34 
AnswerRe: What is a ambiguous line of code! Pin
Pranay Rana25-Aug-15 2:52
professionalPranay Rana25-Aug-15 2:52 
CacheFactory.GetCacheManager();s as already described it part of Microsoft Enterprise library. I used that only . you can search in google using keyword Microsoft Enterprise library.
SuggestionNice Pattern! But implementation could have some improvements Pin
alpham814-Aug-15 14:15
alpham814-Aug-15 14:15 
GeneralRe: Nice Pattern! But implementation could have some improvements Pin
Pranay Rana25-Aug-15 2:50
professionalPranay Rana25-Aug-15 2:50 
QuestionDownload solution missing pieces Pin
Member 1041007612-Aug-15 12:09
Member 1041007612-Aug-15 12:09 
AnswerRe: Download solution missing pieces Pin
RapidGeek13-Aug-15 4:47
professionalRapidGeek13-Aug-15 4:47 
GeneralMy vote of 5 Pin
RapidGeek12-Aug-15 11:52
professionalRapidGeek12-Aug-15 11:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.