Friday, October 28, 2016

Abstract Factory Pattern

What is Abstract Factory Pattern?

Abstract factory pattern is a creational pattern and provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Abstract Factory patterns work around a super-factory which creates other factories. This factory is also called as factory of factories.

The Abstract Factory defines a Factory Method per product.

When to use it?

  1. Create a set of related objects, or dependent objects which must be used together.

  2. System should be configured to work with multiple families of products.

  3. The creation of objects should be independent from the utilizing system.

  4. Concrete classes should be decoupled from clients.

The classes and objects participating in this pattern are:

  • AbstractFactory  (IWaltonFactory)
    • This is an interface which is used to create abstract product.
  • ConcreteFactory  (BangladeshFactory, BhutanFactory)
    • This is a class which implements the AbstractFactory interface to create concrete products.
  • AbstractProduct  (IMobile, IMotorcycle)
    • This is an interface which declares a type of product.
  • Product  (PrimoNx, PrimoZx, Fusion, Xplore)
    • This is a class which implements the AbstractProduct interface to create product.
  • Client  (WaltonClient)
    • This is a class which use AbstractFactory and AbstractProduct interfaces to create a family of related objects.

Real world example:

Let's Walton company has a number of factories throughout the world.

They are building number of products like mobile, motorcycle, television, freez etc.

Client can create any product from any factory. Here I'm showing how we can create a product using Abstract Factory pattern.
  public enum MobileModelType
    {
        PrimoNx,
        PrimoZx
    }

    public enum MotorcycleModelType
    {
        Fusion,
        Xplore
    }

    public interface IWaltonFactory
    {
        IMobile GetMobile(MobileModelType modelType);

        IMotorcycle GetMotorcycle(MotorcycleModelType modelType);
    }
    
    public class BangladeshFactory : IWaltonFactory
    {
        public IMobile GetMobile(MobileModelType modelType)
        {
            IMobile mobile;
            switch (modelType)
            {
                case MobileModelType.PrimoNx:
                    mobile = new PrimoNx();
                    break;
                case MobileModelType.PrimoZx:
                    mobile = new PrimoZx();
                    break;
                default:
                    throw new ApplicationException("Unknown model type");
            }
            mobile.FactoryName = "Bangladesh";
            return mobile;
        }

        public IMotorcycle GetMotorcycle(MotorcycleModelType modelType)
        {
            IMotorcycle motorcycle;
            switch (modelType)
            {
                case MotorcycleModelType.Fusion:
                    motorcycle = new Fusion();
                    break;
                case MotorcycleModelType.Xplore:
                    motorcycle = new Xplore();
                    break;
                default:
                    throw new ApplicationException("Unknown model type");
            }
            motorcycle.FactoryName = "Bangladesh";
            return motorcycle;
        }
    }
    
    public class BhutanFactory : IWaltonFactory
    {
        public IMobile GetMobile(MobileModelType modelType)
        {
            IMobile mobile;
            switch (modelType)
            {
                case MobileModelType.PrimoNx:
                    mobile = new PrimoNx();
                    break;
                case MobileModelType.PrimoZx:
                    mobile = new PrimoZx();
                    break;
                default:
                    throw new ApplicationException("Unknown model type");
            }
            mobile.FactoryName = "Bhutan";
            return mobile;
        }

        public IMotorcycle GetMotorcycle(MotorcycleModelType modelType)
        {
            IMotorcycle motorcycle;
            switch (modelType)
            {
                case MotorcycleModelType.Fusion:
                    motorcycle = new Fusion();
                    break;
                case MotorcycleModelType.Xplore:
                    motorcycle = new Xplore();
                    break;
                default:
                    throw new ApplicationException("Unknown model type");
            }
            motorcycle.FactoryName = "Bhutan";
            return motorcycle;
        }
    }

   
    public interface IMobile
    {
        string FactoryName { get; set; }
        void Create();
    }

   public interface IMotorcycle
    {
        string FactoryName { get; set; }
        void Create();
    }

    public class PrimoNx : IMobile
    {
        public string FactoryName { get; set; }

        public void Create()
        {
            Console.WriteLine($"Primo Nx model mobile has been created from {this.FactoryName}.");
        }
    }

  public class PrimoZx : IMobile
    {
        public string FactoryName { get; set; }

        public void Create()
        {
            Console.WriteLine($"Primo Zx model mobile has been created from {this.FactoryName}.");
        }
    }

   public class Fusion : IMotorcycle
    {
        public string FactoryName { get; set; }

        public void Create()
        {
            Console.WriteLine($"Fusion model motorcycle  has been created from {this.FactoryName}.");
        }
    }

   
    public class Xplore : IMotorcycle
    {
        public string FactoryName { get; set; }

        public void Create()
        {
            Console.WriteLine($"Xplore model motorcycle  has been created from {this.FactoryName}.");
        }
    }

    public class WaltonClient
    {
        private readonly IWaltonFactory factory;

        public WaltonClient(IWaltonFactory factory)
        {
            this.factory = factory;
        }

        public void CreateMobile(MobileModelType modelType)
        {
            var mobile = this.factory.GetMobile(modelType);
            mobile.Create();
        }

        public void CreateMotorcycle(MotorcycleModelType modelType)
        {
            var motorcycle = this.factory.GetMotorcycle(modelType);
            motorcycle.Create();
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            IWaltonFactory waltonBangladeshFactory = new BangladeshFactory();
            WaltonClient waltonClient = new WaltonClient(waltonBangladeshFactory);
            waltonClient.CreateMobile(MobileModelType.PrimoNx);
            waltonClient.CreateMotorcycle(MotorcycleModelType.Fusion);

            IWaltonFactory waltonBhutanFactory = new BhutanFactory();
             waltonClient = new WaltonClient(waltonBhutanFactory);
            waltonClient.CreateMobile(MobileModelType.PrimoZx);
            waltonClient.CreateMotorcycle(MotorcycleModelType.Xplore);

            Console.ReadKey();

        }
    }
  

Here is the output result:

*********************** Bangladesh Factory ********************************
Primo Nx model mobile has been created from Bangladesh.
Fusion model motorcycle  has been created from Bangladesh.



*********************** Bhutan Factory ********************************
Primo Zx model mobile has been created from Bhutan.
Xplore model motorcycle  has been created from Bhutan.


Note

  1. Internally, Abstract Factory use Factory design pattern for creating objects. But it can also use Builder design pattern and prototype design pattern for creating objects. It completely depends upon your implementation for creating objects.

  2. Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.

  3. When Abstract Factory, Builder, and Prototype define a factory for creating the objects, we should consider the following points :

    1. Abstract Factory use the factory for creating objects of several classes.

    2. Builder use the factory for creating a complex object by using simple objects and a step by step approach.

    3. Prototype use the factory for building a object by copying an existing object.

No comments:

Post a Comment