Showing posts with label Factory Pattern. Show all posts
Showing posts with label Factory Pattern. Show all posts

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 –

Monday, June 6, 2016

Builder Pattern

Builder pattern is useful when application needs to create complex object or structure. Builder pattern falls under creational pattern of GOF (Gang of Four) Pattern.

When to use –


Builder Pattern can be implemented in your application when you want to create objects which involves multiple steps or customized user request. With the use of builder pattern, client doesn’t know how object are created inside or how many steps are involved to create an object. Builder Pattern keeps construction logic separate from client.

Major components of Builder Pattern –


Builder – Specifies steps to create product. This is an interface.
Concrete Builder – Create complex product and parts of products via implementing the Builder interface.
Director – This class used to construct an object using Builder interface.
Product – This class represents actual product object which is constructed by the builder pattern.

Let’s say user wants to buy Android mobile phone. Many companies are making Android mobile phones with different specifications. User wants Android mobile which is end product for him or her but specification may vary like processor, ram, screen size, battery capacity etc. See below example how Builder Pattern can be useful to user to get Android mobile phone.

Code –
public enum MobileType
{
    Samsung,
    LG
}
//Builder Interface
public interface IMobileBuilder
{
    void SetModelName(string modelName);
    void SetOperatingSystem(string operatingSystem);
    void SetRAM(string ram);
    void SetProcessor(string processor);
    void SetBattery(string battery);
    void SetScreenSize(string screenSize);
    Mobile GetMobile();
}
//Product class
public class Mobile
{
    public string ModelName { get; set; }
    public string OperatingSystem { get; set; }
    public string RAM { get; set; }
    public string Processor { get; set; }
    public string Battery { get; set; }
    public string ScreenSize { get; set; }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("--------------------------------------------\n");
        sb.Append(string.Format("Model Name - {0},\n", ModelName));
        sb.Append(string.Format("Operating System - {0},\n", OperatingSystem));
        sb.Append(string.Format("RAM - {0},\n", RAM));
        sb.Append(string.Format("Processor - {0},\n", Processor));
        sb.Append(string.Format("Battery - {0},\n", Battery));
        sb.Append(string.Format("Screen Size - {0}\n", ScreenSize));
        sb.Append("--------------------------------------------");
        return sb.ToString();
    }
}
//Concrete Builder
public class AndroidMobileBuilder : IMobileBuilder
{
    Mobile mobile = new Mobile();
       
    public void SetBattery(string battery)
    {
        mobile.Battery = battery;
    }

    public void SetModelName(string modelName)
    {
        mobile.ModelName = modelName;
    }

    public void SetOperatingSystem(string operatingSystem)
    {
        mobile.OperatingSystem = operatingSystem;
    }

    public void SetProcessor(string processor)
    {
        mobile.Processor = processor;
    }

    public void SetRAM(string ram)
    {
        mobile.RAM = ram;
    }

    public void SetScreenSize(string screenSize)
    {
        mobile.ScreenSize = screenSize;
    }
    public Mobile GetMobile()
    {
        return mobile;
    }
}
//Director class
public class MobileCreator
{
    public static IMobileBuilder BuildMobile(MobileType mobileType)
    {
        switch (mobileType)
        {
            case MobileType.Samsung:
                AndroidMobileBuilder androidMobile1 = new AndroidMobileBuilder();
                androidMobile1.SetBattery("3000mah");
                androidMobile1.SetModelName("Samsung Galaxy S5");
                androidMobile1.SetOperatingSystem("Android JellyBean 4.1");
                androidMobile1.SetProcessor("Snap Dragon 1.5Mhz");
                androidMobile1.SetRAM("2 GB");
                androidMobile1.SetScreenSize("5.5 inch");
                return androidMobile1;
            case MobileType.LG:
                AndroidMobileBuilder androidMobile2 = new AndroidMobileBuilder();
                androidMobile2.SetBattery("3200mah");
                androidMobile2.SetModelName("LG Optimus G Pro2");
                androidMobile2.SetOperatingSystem("Android Lollipop 5.1");
                androidMobile2.SetProcessor("Snap Dragon 1.8Mhz");
                androidMobile2.SetRAM("3 GB");
                androidMobile2.SetScreenSize("5.7 inch");
                return androidMobile2;
            default:
                break;
        }
        return null;
    }
}
class Program
{
    static void Main(string[] args)
    {
        //Create and returns Samsung mobile object
        IMobileBuilder mobileBuilder = MobileCreator.BuildMobile(MobileType.Samsung);
        Mobile m = mobileBuilder.GetMobile();
        Console.WriteLine(m.ToString());
        //Create and returns LG mobile object
        mobileBuilder = MobileCreator.BuildMobile(MobileType.LG);
        m = mobileBuilder.GetMobile();
        Console.WriteLine(m.ToString());
        Console.ReadLine();
    }
}


Output –




In above example, user can get Android mobile phone of Samsung/LG brand as per mobile phone’s specifications. This code is written to build mobile phone as per standard specification provided by manufacturer but you can modify code to enter user inputs to build mobile phone device as per user requirement.

Advantages –
  • Encourage code encapsulation for separating construction logic from its client.
  • Easy to extend and maintain.
  • Gives you more control to construction process.
  • More robust as fully constructed object available to the client.

Disadvantages –
  • Builder Pattern requires some code duplication via implementing different products.


Difference between Abstract Factory and Builder Pattern –


Abstract Factory Pattern
Builder Pattern
Focuses on what to build
Focuses on how to build
Depends on other factories to construct object.
Constructs complex object step by step manner.
Builds different types of products from different factories.
Builds complex product.

Hope this article helpful to you. Please leave your feedback in comments below.


References –

See Also – 

Creational Patterns
Structural Patterns
Behavioral Patterns