Wednesday, August 26, 2009

Flyweight Pattern c#.Net

Intent
A high quantity of objects share a common properties object to save space. Flyweight can be used while working with large quantity of similar objects to save memory space.

Non-Software Example
Most telephone subscribers are unaware that the pool of Tone generators (such as dial tone, busy tone or reorder tone) is much smaller than the number of subscribers. The pool of Dial Tone generators is an example of a Flyweight.





Benefits
When we need to create a large amount of objects, each object requires an amount of storage. Even if the size of the objects is small when it comes to a large number of objects the overall required space becomes too high. Some times the creation of small objects reaches a stage that the program cannot execute at all.
This can be addressed with flyweight pattern. With flyweight pattern the object is being crated once and any subsequent request to the same, object is being shared from the earlier created object. Every new request points to the reference of the earlier created object.

UML



Below is the explanation to the UML of the flyweight pattern UML

FlyweightBase: This can be either an interface or an abstract class. When there is no implementation required in the base class we can choose to make it a interface otherwise an abstract class.

ConcreteFlyweight : This class inherits from the FlyweightBase class and holds the stateless information. Stateless information means the same object, so instead of creating a new object the same object can be shared.

UnsharedFlyweight : This class is inherited from FlyweightBase class and holds stateful information. Stateful object means every object will have a specific attribute and behavior.

FlyweightFactory : This class holds references to each of the flyweight objects that have already been created. When the “GetObject” method is called from client code, these references are checked to determine whether appropriate flyweight is already available or not. If one available, it is returned. If not, a new object is created, added to the collection and returned.

The objects in flyweight can be of either of intrinsic and extrinsic. Intrinsic objects are those flyweight objects which are shared. This information is stateless and generally remains unchanged, as any changes would be effectively replicated amongst all of the objects that reference the flyweight. Extrinsic data can be stateful as it is held outside of a flyweight object.

Software Example & Explanation of Code

Flyweight pattern is most useful while building simulation system. In our example let us say we are building a simulation program for a park. So we will be taking a virtual tour of a park. So obliviously when we take a tour it will have trees and cement posts in the park. This example will demonstrate how to apply flyweight pattern in this scenario. We can always say that flyweight uses a form of factory Method pattern.

The first class is the “DisplayUnit” class. This is an abstract class and both the “CementPost” and “Tree” class will inherit from it. Next is the factory which creates the class when not available and if available serves it from the existing objects. Below is the implementation details of each of these class

DisplayUnit.cs

namespace Flyweight
{
public abstract class DisplayUnit
{
public string Name
{
get;
set;
}
public int AboveGround
{
get;
set;
}

public abstract void IsRootVisible(ObjectType objType);
}
}

CementPost.cs

namespace Flyweight
{
class CementPost:DisplayUnit
{

public override void IsRootVisible(ObjectType objType)
{
Console.WriteLine("Root Of {0} Tree not Visible and is above {1} level of ground", objType.objDisplayUnit.Name, objType.objDisplayUnit.AboveGround.ToString());
}
}


}

Tree.cs

namespace Flyweight
{
public class Tree:DisplayUnit
{
public override void IsRootVisible(ObjectType objType)
{
Console.WriteLine("Root Of {0} Tree not Visible and is above {1} level of ground", objType.objDisplayUnit.Name, objType.objDisplayUnit.AboveGround.ToString());
}
}
}

ObjectType.cs

namespace Flyweight
{
public class ObjectType
{
public DisplayUnit objDisplayUnit;
}
}



Let us create a client for this. Let’s say that you are creating two stateless Tree objects. So according to flyweight instead of creating a new object on the second request it should server from the existing object itself.
static void Main(string[] args)
{
DisplayUnitFactory objFactory = new DisplayUnitFactory();

ObjectType objTreeType = new ObjectType();
objTreeType.objDisplayUnit = objFactory.GetObjectType("Tree");

ObjectType objCementPostType = new ObjectType();
objCementPostType.objDisplayUnit = objFactory.GetObjectType("Cement");

ObjectType objTree1 = new ObjectType();
objTree1.objDisplayUnit = objFactory.GetObjectType("Tree");

if (objTreeType.objDisplayUnit == objTree1.objDisplayUnit)
Console.WriteLine("Same object");
else
Console.WriteLine("Different Object");

Console.ReadLine();

}


The output would be the same object hence you will get the out put as “Same Object”. Hope this helps.

The entire source code is available @ http://www.csharppatterns.com/

Happy Coding.

No comments: