Flyweight Design Pattern in C#

Flyweight Design Pattern in C#

In this article, I am going to discuss the Flyweight Design Pattern in C# with some real-time examples. Please read our previous article where we discussed the Proxy Design Pattern in C# with examples. The Flyweight Design Pattern falls under the category of Structural Design Pattern. As part of this article, we are going to discuss the following pointers.

  1. What is the Flyweight Design Pattern?
  2. Understanding the Flyweight Design Pattern with one real-time application.
  3. Understanding the different States in the Flyweight Design Pattern.
  4. Flyweight Design Pattern Class Diagram.
  5. Flyweight Design Pattern Implementation in C#.
  6. When to use the Flyweight Design Pattern in the real-time application?
What is the Flyweight Design Pattern?

The Flyweight Design Pattern is used when there is a need to create a large number of objects of almost similar nature. A large number of objects consumes a large amount of memory and the Flyweight design pattern provides a solution for reducing the load on memory by sharing objects.

This design pattern is basically used to reduce the number of objects created, to decrease the memory footprint, and increase the overall performance of the application. That means this design pattern tries to reduce the already existing similar kind of objects by storing them and create a new object when no matching object is found. If this is not clear at the moment then don’t worry, we will try to understand this with an example.

Understanding the Flyweight Design Pattern:

Please have a look at the following diagram. As you can see in the following image, we created and stored one circle object in the Cache. Here, the circle object that we stored in the cache does not have any color. Suppose, let say we have to create 90000 circle objects which are in green color and 90000 circle objects with blue color. Again we have to create 80000 circle objects which are in orange color and 70000 circle objects with black color. If you notice all the circle object shapes are the same only the color is changed.

Understanding the Flyweight Design Pattern in C#

As per the Flyweight design pattern, we can improve the performance by creating the circle object only one time and reuse that circle object many times to create a different type of colors. Suppose say you want to create 90000 circle objects with green color, then what you can to do is, instead of creating new circle objects every time and fill them with green color, you can get the circle object from the cache and fill that object with green color. Like that you can create 90000 circle objects with green color. So, in this way you can improve the performance of the application.

The different States in the Flyweight Design Pattern:

In the flyweight design pattern, there are two states i.e. Intrinsic and Extrinsic.

Intrinsic states are things that are constants and stored in memory. On the other hand, extrinsic states are things that are not constant and need to be calculated on the Fly and are therefore not stored in the memory.

In our example, the circle shape is constant (it is not changed). That means whether it is a green color circle object and a black color circle object, the shape of the circle object is going to be the same. So, it is stored in the memory i.e. in the cache. And as it is stored in the memory and as it is constant, it belongs to the intrinsic state.

The Extrinsic state is the color of the circle object i.e. for one circle object the color is black and for other circle objects the color is green. The color is not constant and it is calculated on the fly. And therefore the color is not stored in the memory. As a result, the color belongs to the extrinsic state. Now, if you read the definition, then you will understand what is Flyweight Design Pattern it very clearly.

Real-time Example of the Flyweight Design Pattern:

Let us understand the Flyweight Design Pattern with one real-time example. Please have a look at the following image. Most of us know the angry bird video games. Suppose let say in the angry bird’s video game, we want to create 50000 angry birds with red color. So, if we create new 50000 angry birds and fill them with red color, then it will occupy more memory as well as creates memory issues. So, to avoid this, what we can do here is, we can create only one angry bird without any color and put it on the cache. Then, whenever we need any new angry bird object, we just need to get the angry bird object from the cache and fill it with red color. So, in this way, we no need to create new 50000 angry bird objects.

Real-time Example of the Flyweight Design Pattern

In this example, the shape of the angry bird is constant and it is stored in the memory, so the shape of the angry bird is in an intrinsic state. The color of Angry is an extrinsic state because it is not constant. One time the color red another time the color maybe black. That means the color varies on the fly.

Flyweight Design Pattern Class Diagram:

Let us understand the class diagram and the different components involved in the Flyweight Design Pattern. To understand this, please have a look at the following image.

Flyweight Design Pattern Class Diagram

The Flyweight is the interface that has operations that accept ExtrinsicState. There are two concrete classes i.e. ConcreteFlyweight and UnsharedConcreteFlyweight. Both the concrete classes implement the Flyweight interface and provide the implementation for the Operation method. Another class FlyweightFactory. It has the GetFlyweight method which takes the key as a parameter.

The Flyweight interface enables sharing but it does not enforce it. The concrete objects which implement this interface either be shared or unshared.

The ConcreteFlyweight class which implements the Flyweight interface, adds storage for the intrinsic state. It must be shareable and any state we are going to store in this object should be in an intrinsic state.

The unsharedConcreteFlyweight class also implements the Flyweight interface and it adds storage for the particular instance and it is not shared.

The FlyweightFacory has the GetFlyweight method and you have to pass the key to this method. It will check based on the key, whether the flyweight object is there in the cache or not. If it is there then it will return that existing flyweight object. And if it is not there, then it will create a new flyweight object and add that object into the cache and return that flyweight object.

Flyweight Design Pattern Implementation in C#:

Suppose say in your application, you have to create 240000 circle objects with different colors as shown in the below image.

Flyweight Design Pattern Implementation in C#

Let us implement the above example using the Flyweight Design Pattern in C# step by step.

Step1: Creating the Flyweight interface

Create an interface with the name Shape and then copy and paste the following code in it. This interface simply declares one abstract method i.e. Draw(). This method needs to be implemented by the concrete classes.

namespace FlyweightDesignPattern
{
    public interface Shape
    {
        void Draw();
    }
}

Step2: Creating ConcreteFlyweight

Create a class file with the name Circle and then copy and paste the following code in it. As you can see this class implements the Shape interface and provides the implementation for the Draw() method. Basically the Draw method will draw a circle. The circle has four attributes i.e. Color, X Coordinate, Y Coordinate, and Radius. Further, if you notice, the X Coordinate, Y Coordinate, and Radius are fixed i.e. the shape of the circle is fixed. The color is going to vary on the fly i.e. change at run time. So, we created one method i.e. SetColor to set the color of a circle object at runtime.

using System;
namespace FlyweightDesignPattern
{
    public class Circle : Shape
    {
        public string Color { get; set; }
        private int XCor = 10;
        private int YCor = 20;
        private int Radius = 30;
        
        public void SetColor(string Color)
        {
            this.Color = Color;
        }
        public void Draw()
        {
            Console.WriteLine(" Circle: Draw() [Color : " + Color + ", X Cor : " + XCor + ", YCor :" + YCor + ", Radius :"
                    + Radius);
        }
    }
}
Step3: Creating FlyweightFactory

Create a class file with the name ShapeFactory and then copy and paste the following code in it. Here, we created one dictionary collection object which will act as a cache for our application. The dictionary object takes two parameters i.e. the first one is the key which is a string type and the second parameter is its value i.e. the shape object. It has the GetShape method which will take shapeType as a parameter (in our example it is a circle). Then it will check whether that key is present in the dictionary. If it is present then it simply returns the shape object i.e. stored against that key in the dictionary. If the key is not present then it will create a brand new shape object and then add that object into the dictionary and finally return that object to the caller.

using System;
using System.Collections.Generic;
namespace FlyweightDesignPattern
{
   public class ShapeFactory
    {
        private static Dictionary<string, Shape> shapeMap = new Dictionary<string, Shape>();

        public static Shape GetShape(string shapeType)
        {
            Shape shape = null;
            if (shapeType.Equals("circle", StringComparison.InvariantCultureIgnoreCase))
            {
                if (shapeMap.TryGetValue("circle", out shape))
                {
                }
                else
                {
                    shape = new Circle();
                    shapeMap.Add("circle", shape);
                    Console.WriteLine(" Creating circle object with out any color in shapefactory \n");
                }
            }
            return shape;
        }
    }
}
Step4: Client

Please modify the Main method as shown below. This is the client class and used to explain the Flyweight Design Pattern.

using System;
namespace FlyweightDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\n Red color Circles ");
            for (int i = 0; i < 3; i++)
            {
                Circle circle = (Circle)ShapeFactory.GetShape("circle");
                circle.SetColor("Red");
                circle.Draw();
            }

            Console.WriteLine("\n Green color Circles ");
            for (int i = 0; i < 3; i++)
            {
                Circle circle = (Circle)ShapeFactory.GetShape("circle");
                circle.SetColor("Green");
                circle.Draw();
            }

            Console.WriteLine("\n Blue color Circles");
            for (int i = 0; i < 3; ++i)
            {
                Circle circle = (Circle)ShapeFactory.GetShape("circle");
                circle.SetColor("Green");
                circle.Draw();
            }

            Console.WriteLine("\n Orange color Circles");
            for (int i = 0; i < 3; ++i)
            {
                Circle circle = (Circle)ShapeFactory.GetShape("circle");
                circle.SetColor("Orange");
                circle.Draw();
            }

            Console.WriteLine("\n Black color Circles");
            for (int i = 0; i < 3; ++i)
            {
                Circle circle = (Circle)ShapeFactory.GetShape("circle");
                circle.SetColor("Black");
                circle.Draw();
            }

            Console.ReadKey();
        }
    }
}

Output:

When to use the Flyweight Design Pattern in the real-time application?

When to use the Flyweight Design Pattern in the real-time application?

We need to use the Flyweight Design Pattern in real-time applications when

  1. Many similar objects are used and the storage cost is high.
  2. The majority of each object’s state data can be made extrinsic.
  3. A few shared objects would easily replace many unshared objects.
  4. The identity of each object does not matter.

In the next article, I am going to discuss the Behavioral Design Pattern in C# with examples. Here, in this article, I try to explain the Flyweight Design Pattern in C# step by step with an example. I hope you enjoy this Flyweight Design Pattern in C# article.

Leave a Reply

Your email address will not be published. Required fields are marked *