articles

Home / DeveloperSection / Articles / JAVA - AbstractFactory Pattern

JAVA - AbstractFactory Pattern

Tarun Kumar3289 02-Jul-2015

Abstract Factory Pattern  


Previously we learn JAVA - Factory Pattern

 

The Abstract Factory is known as a creational pattern - it's used to construct objects such that they can be decoupled from the implementing system.



The pattern is best utilized when your system has to create multiple families of products or you want to provide a library of products without exposing the implementation details. As you'll have noticed, a key characteristic is that the pattern will decouple the concrete classes from the client.

 

Provides an interface for creating families of related or dependent objects without specifying their concrete classes.



The AbstractFactory class is the one that determines the actual type of the concrete object and creates it, but it returns an abstract pointer to the concrete object just created. 

 

One of the main benefits of this pattern is that the client is totally decoupled from the concrete products. Also, new product families can be easily added into the system, by just adding in a new type of ConcreteFactory that implements AbstractFactory, and creating the specific Product implementations.

 

Implementing an Example:

We are going to create a Shape and Color interfaces and concrete classes implementing these interfaces. We create an abstract factory class AbstractFactory. Factory classes ShapeFactory and ColorFactory are defined where each factory extends AbstractFactory. A factory creator/generator class FactoryProducer is created.



Our demo class uses FactoryProducer to get a AbstractFactory object. It will pass information (CIRCLE / RECTANGLE / SQUARE for Shape) to AbstractFactory to get the type of object it needs. It also passes information (RED / GREEN / BLUE for Color) to AbstractFactory to get the type of object it needs.

 

 

          Create an interface for Shapes.

      // Shape.java

       publicinterfaceShape{

   void draw();

}

         

Create concrete classes implementing the same interface.

// Circle.java

publicclass Circle implements Shape{

   @Override

   publicvoid draw(){

         // TODO Auto-generated method stub

         System.out.println("Inside Circle: draw() method.");

   }

}

// Square.java

publicclass Square implements Shape{

   @Override

   publicvoid draw(){

         // TODO Auto-generated method stub

         System.out.println("Inside Square: draw() method."); 

   }

}

// Rectangle.java

publicclass Rectangle implements Shape{

   @Override

   publicvoid draw(){

         // TODO Auto-generated method stub

         System.out.println("Inside Rectangle: draw() method.");

   }    

}

          Create an interface for Colors.

// Color.java

publicinterfaceColor{

   void fill();

}

          Create concrete classes implementing the same interface.

// Blue.java

publicclass Blue implementsColor{

   @Override

   publicvoidfill() {

         // TODO Auto-generated method stub

         System.out.println("Inside Blue: fill() method.");

   }

}

// Green.java

publicclass Green implements Color{

   @Override

   publicvoid fill() {

         // TODO Auto-generated method stub

         System.out.println("Inside Green: fill() method.");

   }

}

// Red.java

publicclass Red implementsColor{

   @Override

   publicvoidfill() {

         // TODO Auto-generated method stub

         System.out.println("Inside Red: fill() method.");

   }

}

          Create an Abstract class to get factories for Color and Shape Objects.

// AbstractFactory

publicabstractclassAbstractFactory{

   abstract Shape getShape(String shape);

   abstract Color getColor(String color);

} 

          Create Factory classes extending AbstractFactory to generate object of concrete class based on given information.

// ShapeFactory.java

publicclass ShapeFactory extendsAbstractFactory{

   @Override

   Shape getShape(String shapeType) {

         // TODO Auto-generated method stub

         if(shapeType == null){

               returnnull;

         }        

         if(shapeType.equalsIgnoreCase("CIRCLE")){

               returnnew Circle();

         }elseif(shapeType.equalsIgnoreCase("RECTANGLE")){

               returnnew Rectangle();

         }elseif(shapeType.equalsIgnoreCase("SQUARE")){

               returnnew Square();

         }       

         returnnull;

   }      

   @Override

   Color getColor(String color) {

         // TODO Auto-generated method stub

         returnnull;

   }

}

// ColorFactory.java

publicclass ColorFactory extends AbstractFactory{

   @Override

   Shape getShape(String shape) {

         // TODO Auto-generated method stub

         returnnull;

   } 

   @Override

   Color getColor(String color) {

         // TODO Auto-generated method stub     

         if(color == null){

               returnnull;

         }        

         if(color.equalsIgnoreCase("RED")){

               returnnew Red();

         }elseif(color.equalsIgnoreCase("GREEN")){

               returnnew Green();

         }elseif(color.equalsIgnoreCase("BLUE")){

               returnnew Blue();

         }        

         returnnull;

   }

}

          Create a Factory generator/producer class to get factories by passing an information such as Shape or Color

// FactoryProducer

publicclass FactoryProducer {

   publicstatic AbstractFactory getFactory(String choice){      

         if(choice.equalsIgnoreCase("SHAPE")){

               returnnew ShapeFactory();

         }elseif(choice.equalsIgnoreCase("COLOR")){

               returnnew ColorFactory();

         }        

         returnnull;

   }

} 

          Use the FactoryProducer to get AbstractFactory in order to get factories of concrete classes by passing an information such as type.

// AbstractFactoryPatternDemo.java

publicclass AbstractFactoryPatternDemo {

   publicstaticvoid main(String[] args){    

         //.......get shape factory........

         AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");        

         // get an object of Shape Circle

         Shape shape1 = shapeFactory.getShape("CIRCLE");

         // call draw method of Shape Circle

         shape1.draw();        

         // get an object of Shape Rectangle

         Shape shape2 = shapeFactory.getShape("RECTANGLE");

         // call draw method of Shape Rectangle

         shape2.draw();        

         // get an object of Shape Square

         Shape shape3 = shapeFactory.getShape("SQUARE");

         // call draw method of Shape Square

         shape3.draw();        

         //.........get color factory..........

         AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");        

         //get an object of Color Red

         Color color1 = colorFactory.getColor("RED");

         // call fill method of Red

         color1.fill();        

         //get an object of Color Green

         Color color2 = colorFactory.getColor("GREEN");

         // call fill method of Green

         color2.fill();        

         //get an object of Color Blue

         Color color3 = colorFactory.getColor("BLUE");

         // call fill method of Blue

         color3.fill();

   }

}

          Verify the output. 

JAVA - AbstractFactory Pattern

 

Watch Out for the Downsides:


While the pattern does a great job of hiding implementation details from the client, there is always a chance that the underlying system will need to change. We may have new attributes to our AbstractProduct, or AbstractFactory, which would mean a change to the interface that the client was relying on, thus breaking the API.


Updated 07-Sep-2019

Leave Comment

Comments

Liked By