Back to: Design Patterns in C# With Real-Time Examples
Flyweight Design Pattern in C# with Examples
In this article, I am going to discuss the Flyweight Design Pattern in C# with 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.
- What is the Flyweight Design Pattern?
- Understanding the Flyweight Design Pattern with one Real-Time Application.
- Understanding the Different States in the Flyweight Design Pattern.
- Understanding the Flyweight Design Pattern Class or UML Diagram.
- Flyweight Design Pattern Implementation in C#.
- When to use the Flyweight Design Pattern in 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 means it 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, decrease the memory footprint, and increase the overall performance of the application. That means Flyweight Design Pattern tries to reduce the already existing similar kind of objects by storing them in the cache and creating a new object when no matching object is found.
For example, you have one image, and you want thousands of copies of that image. There are two ways to achieve that. In the first approach, we can get the printouts 1000 times that image. The second approach, we can get a printout of that image and then we can use that printout and then we can take 999 xeroxes of that image. Let’s suppose, if the printout for one image is 2 USD, then the total amount required is 1000*2=2000USD. If the xerox price is 1 USD, then the total amount required is 999*1=999 USD, and one printout is 2 USD, so a total of 1001 USD. So, we can save much amount if we follow the second approach. This is also the same in programming. And we can achieve this by using the Flyweight Design Pattern in C#. If this is not clear at the moment then don’t worry, we will try to understand this with an example.
Example to Understand Flyweight Design Pattern in C#:
Please have a look at the following image for a better understanding of the Flyweight Design Pattern. 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’s say we have to create 90000 circle objects which are in green color and 90000 circle objects in blue color. Again we have to create 80000 circle objects which are in orange color and 70000 circle objects in black color. If you notice all the circle object shapes are the same only the color is changed.
As per the Flyweight Design Pattern, we can improve the performance by creating the circle object only one time and reusing that circle object many times to create different types of colors. Suppose, you want to create 90000 circle objects with green color, then what you can do is, instead of creating new circle objects every time and filling them with green color, you can get the circle object from the Cache and fill that object with green color. In the same way, you can create 90000 circle objects with green color. So, in this way, we can improve the performance of the application using the Flyweight Design Pattern in C#.
Different States in Flyweight Design Pattern in C#:
In 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 hence they can not be stored in memory.
In our example, the Circle Shape is constant (it is not changed). That means whether it is a green color circle object or a black color circle object, the shape of the circle object is going to be the same. So, we need to store this circle object 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 very clearly.
Real-Time Example of Flyweight Design Pattern in C#:
Let us understand the Flyweight Design Pattern in C# with one Real-Time Example. Please have a look at the following image. Most of us know the angry bird’s video game. Suppose let’s say in the angry birds video game, we want to create 50000 angry birds with red color. And, 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 memory issue problem, what we can do here is, we can create only one angry bird without any color and put it in 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 are not going to create 50000 angry bird objects.
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 Bird is an extrinsic state because it is not constant. One time the color is red another time the color may be black. That means the color varies on the fly.
Flyweight Design Pattern Class or UML Diagram:
Let us understand the Class Diagram or UML Diagram and understand the different components involved in the Flyweight Design Pattern in C#. For a better understanding, please have a look at the following diagram.
The following are the three components involved in the Flyweight Design Pattern.
- Flyweight: The Flyweight interface enables sharing but it does not enforce it. The concrete objects which implement this interface either be shared or unshared. This is going to be an interface that defines the members of the flyweight objects.
- ConcreteFlyweight: 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.
- FlyweightFacory: 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 to the cache and return that flyweight object.
Implementing Flyweight Design Pattern in C#:
Suppose in your application, you want to create 240000 circle objects with different colors as shown in the below image.
Let us implement the above example using the Flyweight Design Pattern using C# step by step to improve the overall performance of the application.
Step 1: Creating Flyweight Interface
Create an interface with the name IShape.cs and then copy and paste the following code into it. This interface simply declares one abstract method i.e. Draw(). This method needs to be implemented by the concrete classes.
namespace FlyweightDesignPattern { // Flyweight Interface // This is an interface that defines the members of the flyweight objects. public interface IShape { void Draw(); } }
Step 2: Creating ConcreteFlyweight
Create a class file with the name Circle.cs and then copy and paste the following code into it. As you can see this class implements the IShape 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 { // ConcreteFlyweight // This is a class which is Inherits from the Flyweight Interface. public class Circle : IShape { public string Color { get; set; } //The following Properties Values are going to be the same for all Circle Shape Object private readonly int XCor = 10; private readonly int YCor = 20; private readonly int Radius = 30; //For Each Circle Object, we need to call the Following Method to set the Color public void SetColor(string Color) { this.Color = Color; } public void Draw() { Console.WriteLine(" Circle: Draw() [Color : " + Color + ", X Cor : " + XCor + ", YCor :" + YCor + ", Radius :" + Radius); } } }
Step 3: Creating FlyweightFactory
Create a class file with the name ShapeFactory.cs and then copy and paste the following code into 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 or not. If the key is present in the dictionary, then it simply returns the shape object i.e. stored against that key in the dictionary. If the key is not present in the dictionary, then it will create a brand new shape object and then add that object to the dictionary and finally return that object to the caller.
using System; using System.Collections.Generic; namespace FlyweightDesignPattern { // FlyweightFacory // This is a factory class used to create concrete objects of the ConcreteFlyweight type public class ShapeFactory { //The Following Dictionary is going to act as our Cache Memory private static Dictionary<string, IShape> shapeMap = new Dictionary<string, IShape>(); //The following Method is going to return the Shape Object public static IShape GetShape(string shapeType) { IShape shape = null; if (shapeType.Equals("circle", StringComparison.InvariantCultureIgnoreCase)) { //If the key shapeType i.e. circle is stored in the Cache, then return the value of the key //else create circle object, store it in the Cache, and return the object 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
The Main method of the Program class is going to be the Client. So, please modify the Main method of the Program class as shown below. This is the client class and is used to explain the Flyweight Design Pattern. The following code is self-explained, so please go through the comment lines for a better understanding.
using System; namespace FlyweightDesignPattern { class Program { static void Main(string[] args) { //Creating Circle Objects with Red Color Console.WriteLine("\n Red color Circles "); for (int i = 0; i < 3; i++) { Circle circle = (Circle)ShapeFactory.GetShape("circle"); circle.SetColor("Red"); circle.Draw(); } //Creating Circle Objects with Green Color Console.WriteLine("\n Green color Circles "); for (int i = 0; i < 3; i++) { Circle circle = (Circle)ShapeFactory.GetShape("circle"); circle.SetColor("Green"); circle.Draw(); } //Creating Circle Objects with Blue Color Console.WriteLine("\n Blue color Circles"); for (int i = 0; i < 3; ++i) { Circle circle = (Circle)ShapeFactory.GetShape("circle"); circle.SetColor("Green"); circle.Draw(); } //Creating Circle Objects with Orange Color Console.WriteLine("\n Orange color Circles"); for (int i = 0; i < 3; ++i) { Circle circle = (Circle)ShapeFactory.GetShape("circle"); circle.SetColor("Orange"); circle.Draw(); } //Creating Circle Objects with Black Color 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 Real-Time application?
We need to use the Flyweight Design Pattern in Real-Time applications, when
- Many similar objects are used and the storage cost is high.
- The majority of each object’s state data can be made extrinsic.
- A few shared objects would easily replace many unshared objects.
- 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# with Examples. I hope you enjoy this Flyweight Design Pattern in C# with Examples article.
In the factory, you should try to get the value from the map first.
Because if you have several shape (circle, rectangle, square, etc), you don’t want to repeat the mapShape.TryGetValue
Something like
GetShape(string shapeType) {
if (!mapShape.TryGetValue(shapeType, out Shape shape)
{
if (shape.Equals(“circle”))
else …
}
return shape;
}