Before reading this article, please go through the following articles:
- Design Patterns: Introduction
- Learn Design Pattern - Singleton Pattern
- Learn Design Pattern - Factory Method Pattern
- Learn Design Pattern - Abstract Factory Pattern
- Learn Design Pattern - Builder Pattern
- Learn Design Pattern - Prototype Pattern
- Learn Design Pattern - Adapter Pattern
- Learn Design Pattern - Composite Pattern
- Learn Design Pattern - Decorator Pattern
- Learn Design Pattern - Facade pattern
In the previous article we discussed Facade Pattern.
Today we will understand what Flyweight Pattern is and how to implement it in an ASP.Net application.
Agenda
- What is Flyweight Pattern?
- When to use Flyweight Pattern?
- Components involved in Flyweight Pattern.
- Implement a Flyweight Pattern using ASP.Net application.
- Class Diagram.
What is Flyweight Pattern?
According to the GOF the "Flyweight pattern is used when one instance of a class can be used to provide many virtual instances.".
When to Use?
Flyweight is used when there is a need to create a large number of objects of almost similar nature. The large number of objects consume a large amount of memory and the Flyweight design pattern provides a solution for reducing the load on memory by sharing objects.
For instance we can use the example of a popular video game Mario. It has the two characters, Mario and Luigi. Both have the same abilities and characteristics, the only difference is their color and name.
Take an example of an adventure game where we may see a huge number (maybe millions) of characters and most of them are the same, having a slight difference in some characteristics (many times all are 100% same).
Creating a new instance for every character may impact performance significantly.
Flyweight Pattern as solution
In the Flyweight Pattern:
- An Object is created for one character.
- The Character is rendered using the render method.
- The same Object is reused if another similar character is required.
Now when we talk about objects, they have states which may either be an intrinsic state or an extrinsic state, as in:
- Intrinsic states are things that are constant such as what a type of weapon character has (All Gun Soldiers will have a Gun as a weapon, a Sword solider will have a sword as a weapon etc.)
- Whereas Extrinsic states are things that are not constant and need to be calculated on the fly like color (some characters equipped with a gun may be in red color and some in blue)
The big question is how to work with an extrinsic state if we are going to share the same object. We can understand this once we look at the sample.
Components involved in the Flyweight pattern are:
- Abstract Flyweight
- ConcreteFlyweight
- FlyweightFactory
Code Walkthrough
Output
Step 1
Create an Abstract Flyweight class Soldier as:
public abstract class Soldier
{
public WeaponType Weapon{get;set;}
public abstract void RenderSoldier(string StrPriName, string Color);
}
Step 2
Create a Concrete Flyweight classes GunSoldier and SwordSoldier as:
public class GunSoldier:Soldier
{
public GunSoldier()
{
this.Weapon = WeaponType.Gun;
}
public override void RenderSoldier(string StrPriName, string Color)
{
HttpContext.Current.Response.Write("Gun Character " + StrPriName + " Rendered with "+Color+" Color");
}
}
public class SwordSoldier:Soldier
{
public SwordSoldier()
{
this.Weapon = WeaponType.Sword;
}
public override void RenderSoldier(string StrPriName, string Color)
{
HttpContext.Current.Response.Write("Sword Character " + StrPriName + " Rendered with " + Color + " Color");
}
}
Step 3
Create a Flyweight Facttory SoldierFactory as:
public class SoldierFactory
{
Dictionary<string, Soldier> SoldierCollection;
public SoldierFactory()
{
SoldierCollection = new Dictionary<string, Soldier>();
}
public Soldier GetSoldier(string SoldierIndex)
{
if(!SoldierCollection.ContainsKey(SoldierIndex))
{
HttpContext.Current.Response.Write("Objet created - ");
switch(SoldierIndex)
{
case "0":
SoldierCollection.Add(SoldierIndex, new GunSoldier());
break;
case "1":
SoldierCollection.Add(SoldierIndex, new SwordSoldier());
break;
}
}
else
{
HttpContext.Current.Response.Write("Objet reused - ");
}
return SoldierCollection[SoldierIndex];
}
}
Step 4
Write the client code as:
this.CreateSoldier(DdlCharacterType1, TxtCharacterName1, TxtColor1);
Response.Write("<Br>");
this.CreateSoldier(DdlCharacterType2, TxtCharacterName2, TxtColor2);
Response.Write("<Br>");
this.CreateSoldier(DdlCharacterType3, TxtCharacterName3, TxtColor3);
.
.
.
private void CreateSoldier(DropDownList DdlCharacterType, TextBox TxtCharacterName, TextBox TxtColor)
{
Soldier soldier = factory.GetSoldier(DdlCharacterType.SelectedValue);
soldier.RenderSoldier(TxtCharacterName.Text,TxtColor.Text);
}
You can see we are creating just 2 objects, one for GunSoldier and another for Sword soldier.
Download the sample code attached for a full demonstration.
Note: The Flyweight pattern uses the Factory Method pattern internally.
Class Diagram
Hope you enjoyed reading this article.
Suggestions and feedback are always welcome.