Design Patterns: The Abstract Factory

author-image
CIOL Bureau
Updated On
New Update

Avijeet Dash and Satyabrata Dash

Advertisment

Intent


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

There are five creational patterns, namely: the Abstract Factory, Factory
Method, Builder, Prototype and Singleton. In this tutorial on software design
pattern, we take a look at the intricacies of the Abstract Factory method. This
session will provide an interface for creating families of related or dependent
objects without specifying their concrete classes.

Advertisment

In 30 seconds

The catch here is "families of related or dependent objects".
Each family of objects has a similar class hierarchy (say a set of widget
classes like text, checkbox, window, etc. for multiple look and feel, i.e.
windows family of objects, motif family of objects). This pattern helps in
switching from one hierarchy to another with minimal change in code. As a
factory class object creates all the objects, by just changing the factory
object in the client code, we can easily switch over to other related objects.
The client code remains isolated from the actual object created.

Structure

https://www.ciol.com/images/sw_desg_pttn_Jun18.gif

Advertisment

Motivation

The foremost benefit of Abstract Factory is that it abstracts the object
creation process and thus stops hard coding of object creation in client code.
The other benefit we achieve is extensibility. Whenever we need new kind of
products to be created we can make new concrete factory classes.

The Abstract Factory provides the product creation interface, which is
implemented by the concrete factories. Each product has an abstract class, which
provides the product interface. Abstract Factory uses factory method pattern to
delegate the real object creation task to the concrete factory classes. This
pattern helps exchanging product families easily, by simply changing the
concrete factory object in the code. Clients manipulate instances through their
abstract interfaces so that the concrete product classes are isolated.

Advertisment

Sample Code

Example:

/*

We have two kinds of products: A1, A2 and B1, B2 extending respective
abstract product class. To create each of these products there are two concrete
factory classes, ConcreteFactory1 and ConcreteFactory2 extending from Abstract Factory class
productfactory. We have also used a factory maker class that accepts an argument
from client and decides the concrete factory to be instantiated.

*/

Advertisment

//Abstract Factory

abstract class AbstractFactory{

abstract AbstractProductA createProductA();

abstract AbstractProductB createProductB();

}

// Concrete Factory1

class ConcreteFactory1 extends AbstractFactory{

AbstractProductA createProductA(){

return new ProductA1("ProductA1");

}

AbstractProductB createProductB(){

return new ProductB1("ProductB1");

}

}

Advertisment

// Concrete Factory2

class ConcreteFactory2 extends AbstractFactory{

AbstractProductA createProductA(){

return new ProductA2("ProductA2");

}

AbstractProductB createProductB(){

return new ProductB2("ProductB2");

}

}

//Abstract ProductA

abstract class AbstractProductA{

//public abstract void operationA1();

//public abstract void operationA2();

}

Advertisment

//Abstract ProductB

abstract class AbstractProductB{

//public abstract void operationB1();

//public abstract void operationB2();

}

//ProductA1

class ProductA1 extends AbstractProductA{

ProductA1(String arg){

System.out.println("Hello "+arg);

}

// Implement the code here

}

class ProductA2 extends AbstractProductA{

ProductA2(String arg){

System.out.println("Hello "+arg);

}

// Implement the code here

}

class ProductB1 extends AbstractProductB{

ProductB1(String arg){

System.out.println("Hello "+arg);

}

// Implement the code here

}

class ProductB2 extends AbstractProductB{

ProductB2(String arg){

System.out.println("Hello "+arg);

}

// Implement the code here

}

//Factory creator - an indirect way of instantiating the factories

class FactoryMaker{

private static AbstractFactory pf=null;

static AbstractFactory getFactory(String choice){

if(choice.equals("a")){

pf=new ConcreteFactory1();

}else if(choice.equals("b")){

pf=new ConcreteFactory2();

}

return pf;

}

}

// Client

public class Client{

public static void main(String args<>){

AbstractFactory pf=FactoryMaker.getFactory("a");

AbstractProductA product=pf.createProductA();

//more function calls on product

System.out.println("This is a Abstract Factory pattern example" );

}

}

This is a simple example. In reality, the product class would be composed of
many components, which needs to be created in the factory. To have a new kind of
a product as a variation to type A, we simply have to add another factory
extending ConcreteFactory1 and pass an object to client without any other change
to client code.

Complexities simplified

One important issue here is extensibility, when we want to add another family
of products: we have to create another concrete
factory class. Several product types can be painful and to avoid parallel
hierarchy of ConcreteFactories with respect to the products, we can have one
ConcreteFactory, which uses a "prototype-based" approach where the concrete
factory is initialized with a prototypical instance of each product in the
family, and it creates a new product by cloning its prototype. More on this
will be presented in prototype pattern.

When new products are added in the family, one new factory method needs to be
added in the ConcreteFactory. This can be managed by having one factory method
taking the kind of product object, as argument along with parameters to
initialize. This approach can be safely used with prototype-based factories.

The concrete factory can be implemented as a singleton as we can use only one
factory to create all the related objects of one product family. This is also
known as related patterns.

Also Known as and Related Patterns

It’s also known as kit, and it is very strongly
related to singleton, prototype and factory method.

(The authors are senior developers at MindTree Consulting. They can be
reached at avijeetd@mindtree.com
and
satyabrata_dash@mindtree.com.
References: Design Patterns, elements of reusable object-oriented software by
Gamma, Helm, Johnson and Design Patterns in Java by James W. Cooper)

tech-news