Gang of Four Creational pattern: AbstractFactory
Creational Pattern
Creates an instance of several families of classes. Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
The idea behind the AbstractFactory pattern is that the implementation of some functionality can be changed by plugging in a different Factory.
None of the calling code in the application needs to change to accommodate a different factory apart from the code that decides which Factory to use.
To get the code for this example:
git clone https://github.com/spotadev/gangoffour.git
In src/main/java navigate to this package:
com.javaspeak.designpatterns.go4.creational.abstractfactory
You can run the code from the main method of:
AbstractFactoryApplication
In this example the application retrieves a factory; then from the factory it gets a shape which it then draws. If the SquareFactory is plugged in, then a Square is drawn. If the TriangleFactory is plugged in a Tringle is drawn.
The calling code in the application looks like:
public void drawShapes(){
ShapeSelector.getShapeFactory( ShapeType.SQUARE ).getShape().drawShape();
ShapeSelector.getShapeFactory( ShapeType.TRIANGLE ).getShape().drawShape();
}
Notice that a ShapeSelector is used to return SquareFactory or a TriangleFactory. Notice that getShape() is then called on the factory which returns a Square or Triangle depending on whether the factory is a SquareFactory or a TriangleFactory. Finally drawShape() is called. If the shape is a Square a Square is drawn while if the shape is a Triangle a Triangle is drawn:
X X X X
X X
X X
X X X X
x
x x
x x
x x
x x x x x
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
import com.javaspeak.designpatterns.go4.creational.abstractfactory.ShapeSelector.ShapeType;
/**
* Text book description:
* <ul>
* "Abstract Factory: Creates an instance of several families of classes. Provide an
* interface for creating families of related or dependent objects without specifying
* their concrete classes."
* </ul>
* The idea behind the AbstractFactory pattern is that the implementation of some functionality
* can be changed by plugging in a different Factory.
* <p>
* None of the calling code in the application needs to change to accommodate a different factory
* apart from the code that decides which Factory to use.
* <p>
* In the code example the application retrieves a factory; then from the factory it gets a
* shape which it then draws. If the SquareFactory is plugged in, then a Square is drawn.
* If the TriangleFactory is plugged in a Triangle is drawn.
* <p>
* The calling code in the application looks like:
* <pre>
* public void drawShapes(){
*
* ShapeSelector.getShapeFactory( ShapeType.SQUARE ).getShape().drawShape();
* ShapeSelector.getShapeFactory( ShapeType.TRIANGLE ).getShape().drawShape();
* }
* </pre>
* Notice that a ShapeSelector is used to return SquareFactory or a TriangleFactory. Notice that
* getShape() is then called on the factory which returns a Square or Triangle depending on
* whether the factory is a SquareFactory or a TriangleFactory. Finally drawShape() is called.
* If the shape is a Square a Square is drawn while if the shape is a Triangle a Triangle is drawn:
* <pre>
* X X X X
* X X
* X X
* X X X X
*
*
* x
* x x
* x x
* x x
* x x x x x
*</pre>
*
* @author John Dickerson - 22 Feb 2020
*/
public class AbstractFactoryApplication {
public void drawShapes() {
ShapeSelector.getShapeFactory( ShapeType.SQUARE ).getShape().drawShape();
ShapeSelector.getShapeFactory( ShapeType.TRIANGLE ).getShape().drawShape();
}
public static void main( String[] args ) {
AbstractFactoryApplication application = new AbstractFactoryApplication();
application.drawShapes();
}
}
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
/**
* The ShapeSelector is responsible for returning the correct ShapeFactory. The ShapeFactory can
* be either a SquareFactory or a TriangleFactory.
*
* @author John Dickerson - 22 Feb 2020
*/
public class ShapeSelector {
enum ShapeType {
SQUARE, TRIANGLE;
}
/**
* Returns the appropriate ShapeFactory for the ShapeType
*
* @param shapeType
* Enum specifying Shape type
*
* @return
* Factory that implements ShapeFactory
*/
public static ShapeFactory getShapeFactory( ShapeType shapeType ) {
switch ( shapeType ) {
case TRIANGLE:
return new TriangleFactory();
case SQUARE:
return new SquareFactory();
default:
throw new UnsupportedOperationException( "Not supported" );
}
}
}
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
/**
* SquareFactory and TriangleFactory implement ShapeFactory. ShapeFactory is the cornerstone of
* the Gang of Four Structural AbstractFactory pattern.
* <p>
* Depending on whether SquareFactory or TriangleFactory is plugged in, a Square or Triangle will
* be used when the drawShape() method is called on the Shape.
*
* @author John Dickerson - 22 Feb 2020
*/
public interface ShapeFactory {
/**
* Returns a shapw the the implentation of the ShapeFactory deals with.
* <p>
* For example a SquareFactory that implements ShapeFactory will return a Square
*
* @return
* a Shape
*/
Shape getShape();
}
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
/**
* Square and Triangle implement Shape
*
* @author John Dickerson - 22 Feb 2020
*/
public interface Shape {
/**
* Draws a Shape
*/
public void drawShape();
}
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
/**
* Implementation of ShapeFactory which returns a Square when the getShape()
* method is called.
*
* @author John Dickerson - 22 Feb 2020
*/
public class SquareFactory implements ShapeFactory {
@Override
public Shape getShape() {
return new Square();
}
}
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
/**
* Implementation of Shape. When the drawShape() method is called draws a
* Square
*
* @author John Dickerson - 22 Feb 2020
*/
public class Square implements Shape {
@Override
public void drawShape() {
StringBuilder sb = new StringBuilder( "\n" );
sb.append( "X X X X\n" );
sb.append( "X X\n" );
sb.append( "X X\n" );
sb.append( "X X X X\n" );
System.out.println( sb.toString() );
}
}
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
/**
* Implementation of ShapeFactory which returns a Triangle when the getShape()
* method is called.
*
* @author John Dickerson - 22 Feb 2020
*/
public class TriangleFactory implements ShapeFactory {
@Override
public Shape getShape() {
return new Triangle();
}
}
package com.javaspeak.designpatterns.go4.creational.abstractfactory;
/**
* Implementation of Shape. When the drawShape() method is called draws a
* Triangle
*
* @author John Dickerson - 22 Feb 2020
*/
public class Triangle implements Shape {
@Override
public void drawShape() {
StringBuilder sb = new StringBuilder( "\n" );
sb.append( " x \n" );
sb.append( " x x \n" );
sb.append( " x x \n" );
sb.append( " x x \n" );
sb.append( "x x x x x\n" );
System.out.println( sb.toString() );
}
}
Back: Gang of Four
Page Author: JD