Thursday, December 26, 2013

Abstract Factory Design Pattern

Abstract Factory ( Creational Design Pattern )



The abstract factory pattern is a software creational design pattern that provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.  or in similar way we can say as 
The Abstract Factory design pattern (part of the Gang of Four) falls under the Creational design pattern category and it provides a way to encapsulate a group of factories that have a common link without highlighting their concrete classes. 
This is all about a factory creating various objects at run time based on user demand. The client remains completely unaware (decoupled) on which concrete products it gets from each of these individual factories and the client is only able to access a simplified interface.

The essence of the Abstract Factory Pattern is to "Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

As intent of any Creational design pattern is to avoid using of "new" operator 





Abstract Factory patterns works around a super-factory which creates other factories. This factory is also called as Factory of factories. In Abstract Factory pattern an interface is responsible for creating a factory of related objects, without explicitly specifying their classes. This pattern is one level of abstraction higher than factory pattern.
 

As there is a word ‘abstract’ in the pattern name don’t mistake and confuse it with java ‘abstract’ keyword .  It considered as another layer of abstraction over factory pattern.
 

e.g. In Java while doing XML work with DOM Parser , we have used DocumentBuilderFactory   class which is an example abstract factory design pattern because it returns a factory called DocumentBuilder which then used to create Document.

//Example of Abstract Factory and Factory design pattern  in Java
DocumentBuilderFactory abstractFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder factory = abstractFactory.newDocumentBuilder();
Document doc = factory.parse(stocks)

In this example DocumentBuilderFactory (Abstract Factory) creates DocumentBuilder (Factory) which creates Documents (Products).

In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interfaces to create the concrete objects that are part of the theme. The client does not know (or care) which concrete objects it gets from each of these internal factories, since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface


Example : The best example will be configuring Database connection factory which hide underline Database type. We can configure Oracle, DB2 or Sybase Connection Factory in application.
    1)  java.util.Calendar#getInstance()
    2) java.text.NumberFormat#getInstance()



Running Example

1)  Let's assume we are startup company who want to manufacture different types of cars .  We have below 3 types of cars in the production unit.

We have created enum of those types


public enum CarType {

      SMALL, SEDAN, LUXURY
}



We have different locations all over the globe where we want to open franchise




public enum Location {
    INDIA , USA , DEFAULT , EUROPE , ASIA
}


Let's define abstract class for all cars and then we can construct each type as per specific requirement .



public abstract class Car {
      private CarType model = null;
      private Location location = null;
     
      public Car(CarType model, Location location){
             this.model = model;
             this.location = location;
             }
             
      protected abstract void construct();

      public CarType getModel() {
            return model;
      }

      public void setModel(CarType model) {
            this.model = model;
      }

      public Location getLocation() {
            return location;
      }

      public void setLocation(Location location) {
            this.location = location;
      }
     
      @Override
      public String toString() {
            return "Model- "+model + " built in "+location;
           
      }
}



OK , so now we have abstract class where we have taken help from mechanical engineer team and define basic parameters . 

Now we are standing in production unit where we  can actually "construct" car as per design approved by team. 

Here we go with Small Car where we are just putting system out to display we are constructing car. 


public class SmallCar extends Car{
     
      public SmallCar(Location location){
            super(CarType.SMALL, location);
      }

      @Override
      protected void construct() {
            System.out.println("Building SMALL car");
           
      }

}



Now we have some experience of constructing small car , now lets do some thing more :)



public class SedanCar extends Car{
     
      public SedanCar(Location location){
            super(CarType.SEDAN, location);
      }

      @Override
      protected void construct() {
            System.out.println("Building SEDAN car");
           
      }
}


Let's construct luxury car


public class LuxuryCar extends Car{
     
      public LuxuryCar(Location location){
            super(CarType.LUXURY, location);
      }

      @Override
      protected void construct() {
            System.out.println("Building luxury car");
           
      }

}


We have all 3 model's developed .  Now we can go for constructing the Factory for those 



1)  public class DefaultCarFactory {
            Car car = null;
      public static Car buildCar(CarType model){
            switch (model){
            case SMALL:
                  car = new SmallCar(Location.DEFAULT);   
                  break;
            case SEDAN:
                  car = new SedanCar(Location.DEFAULT);      
                  break;
            case LUXURY:
                  car = new LuxuryCar(Location.DEFAULT);    
                  break;     
            }
            return car;
      } }


2)  public class AsiaCarFactory {
            Car car = null;
      public static Car buildCar(CarType model){
            switch (model){
            case SMALL:
                  car = new SmallCar(Location.ASIA);        break;
            case SEDAN:
                  car = new SedanCar(Location.ASIA);        break;
            case LUXURY:
                  car = new LuxuryCar(Location.ASIA);       break;     
           
            }
            return car;
      }}





3)  public class USACarFactory {
            Car car = null;
      public static Car buildCar(CarType model){
            switch (model){
            case SMALL:
                  car = new SmallCar(Location.USA);   break;
            case SEDAN:
                  car = new SedanCar(Location.USA);   break;
            case LUXURY:
                  car = new LuxuryCar(Location.USA); break;     
            }
            return car;
      }
}


Here the heart of our factory is CarFactory


 public class CarFactory {

      private CarFactory() { }

     
      public static Car buildCar(CarType type)
      {
            Car car = null;
            Location location = Location.ASIA;
            switch(location)
            {
            case USA:
                  car = USACarFactory.buildCar(type); break;
                 
            case ASIA:
                   car = AsiaCarFactory.buildCar(type);  break;
                   
            case DEFAULT:
                  car = DefaultCarFactory.buildCar(type); break;
            }
            return car;
      }
}
 




All things done , now lets give franchises and earn some money :) 



public class TestFactoryPattern {

     /**
      * @param args
      */
     public static void main(String[] args) {

          System.out.println(CarFactory.buildCar(CarType.SMALL));
          System.out.println(CarFactory.buildCar(CarType.SEDAN));
          System.out.println(CarFactory.buildCar(CarType.LUXURY));

     }
}



Abstract Factories are great for supporting multiple platforms while keeping your code-base unified. Suppose you have a large Qt or GTK+ or .NET/Mono program that you want to run on Windows, Linux, and OSX. But you have a feature that is implemented in a different way on each platform (perhaps via the kernel32 API or a POSIX feature).
public abstract class Feature
{
    public abstract int PlatformSpecificValue { get; }

    public static Feature PlatformFeature
    {
        get
        {
            string platform;
            // do platform detection here
            if (platform == "Win32")
                return new Win32Feature();
            if (platform == "POSIX")
                return new POSIXFeature();
        }
    }

    // platform overrides omitted
}
With this Abstract Factory, your UI doesn't need to know anything about the current platform.
Feature feature = Feature.PlatformFeature;
Console.WriteLine(feature.PlatformSpecificValue);

 
Alternative approach for design pattern
1)  Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used profitably. At other times they are complementary: Abstract Factory might store a set of Prototypes from which to clone and return product objects, Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementation.
2) Abstract Factory can be used as an alternative to Façade pattern to hide platform specific classes
3) AbstractFactory class declares only an interface for creating the products. The actual creation is the task of the ConcreteProduct classes, where a good approach is applying the Factory Method design pattern for each product of the family.
4)  Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype.

 
Most Discussion question in universe of design pattern :) 

Difference between Abstract Factory and Factory Method pattern:
  • Factory Method pattern exposes a method to the client for creating the object whereas in case of Abstract Factory they expose a family of related objects which may consist of these Factory methods.
  • Designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
  • Factory Method pattern hides the construction of single object where as abstract factory method hides the construction of a family of related objects. Abstract factories are usually implemented using (a set of) factory methods.


Keep in Mind 





progress

No comments: