Sunday, September 25, 2016

Flyweight Pattern


Flyweight pattern allow us to reuse memory space via reducing similar kind of object creation. Flyweight pattern falls under structural pattern of GOF (Gang of Four) patterns.

When to use –


Flyweight pattern can be used in scenarios where memory is major constraint. Flyweight pattern reuses already created similar objects and stores them and creates new object only when no similar object found. So by doing this it reduces number of new objects created and decrease memory usage. Flyweight pattern uses sharing mechanism to support large number of objects efficiently.

Major components of Flyweight pattern –


Flyweight – This is an interface defines the members of flyweight class.
Concrete Flyweight – This is concrete class which implements flyweight interface.
Unshared Concrete Flyweight – This is concrete class which implements flyweight interface and not shared.
Flyweight Factory – This class acts as factory and creates different types of objects as per client request. This class also ensures that it will return shared object if already created.
Client – This is client class and has reference to flyweight interface and request flyweight factory to get shared/unshared objects.

See below example of Flyweight pattern.

Code –
class Program
{
    //types of shape
    public enum ShapeType
    {
        Rectanlge,
        Circle,
        Triangle
    }
    //Flyweight
    public interface IShape
    {
        void Draw(int cordinates);
    }
    //concrete flyweight
    public class Rectangle : IShape
    {
        public void Draw(int size)
        {
            Console.WriteLine("Drawing rectangle of size {0}", size);
        }
    }
    //concrete flyweight
    public class Circle : IShape
    {
        public void Draw(int size)
        {
            Console.WriteLine("Drawing circle of size {0}", size);
        }
    }
    //unshared concrete flyweight
    public class Triangle : IShape
    {
        public void Draw (int size)
        {
            Console.WriteLine("Drawing triangle of size {0}", size);
        }
    }
    //Flyweight factory class
    public class ShapeFactory
    {
        public Dictionary<ShapeType, IShape> myShapes = new Dictionary<ShapeType, IShape>();
        public IShape GetShape(ShapeType shapeType)
        {
            if (myShapes.Keys.Contains(shapeType))
            {
                //reusing existing object
                Console.WriteLine("Similar type of object is already exist and reusing the same");
                return myShapes[shapeType];
            }
            else
            {
                //if object is not created yet, create using factory pattern
                switch (shapeType)
                {
                    case ShapeType.Rectanlge:
                        IShape rectangle = new Rectangle();
                        myShapes.Add(ShapeType.Rectanlge, rectangle);
                        break;
                    case ShapeType.Circle:
                        IShape circle = new Circle();
                        myShapes.Add(ShapeType.Circle, circle);
                        break;
                    case ShapeType.Triangle:
                        IShape triangle = new Triangle();
                        return triangle;
                    default:
                        Console.WriteLine("No shape found");
                        break;
                }
                return myShapes[shapeType];
            }
        }

    }

    //Client
    static void Main(string[] args)
    {
        ShapeFactory shapeFactory = new ShapeFactory();
        IShape rectangle = shapeFactory.GetShape(ShapeType.Rectanlge);
        rectangle.Draw(100);
        IShape circle = shapeFactory.GetShape(ShapeType.Circle);
        circle.Draw(50);

        //Shape factory returns already existing objects instead of creating new
        IShape rect_exist = shapeFactory.GetShape(ShapeType.Rectanlge);
        rect_exist.Draw(80);
        IShape circ_exist = shapeFactory.GetShape(ShapeType.Circle);
        circ_exist.Draw(40);

        //triangle object is not shared so new object will be created everytime
        IShape triangle1 = shapeFactory.GetShape(ShapeType.Triangle);
        triangle1.Draw(30);
        IShape triangle2 = shapeFactory.GetShape(ShapeType.Triangle);
        triangle2.Draw(31);

        Console.ReadLine();
    }
}

Output –



As you can see in above example, Flyweight pattern uses flyweight factory to create object and manage them. Flyweight factory creates objects and store them, if object is already created it will return the existing object and if not then it will create new object and return. Flyweight factory also manages unshared objects which will be always created returned and never stored. This way flyweight enforces reusability of existing object and reduce memory usage.

I hope this article helps you to know more about Flyweight Pattern. Please leave your feedback in comments section below.

References –

See Also –