Design Patterns Tutorial
A tutorial on GOF design patterns. This tutorial is for beginners who are going to learn design patterns for the first time. Each pattern is expalined with suitable examples.

24/11/2013 Categories: Creational Patterns. No Comments on Abstract Factory Pattern

Intent:

Abstract factory provides an interface to create a family of related objects, without explicitly specifying their concrete classes.

 

Also Known As:

Kit.

 

Motivation:

Modularization is a big issue in today’s programming. Programmers are trying to avoid the idea of adding more code to the existing classes to encapsulate more general information. Let’s consider an example of user interface toolkit which supports multiple look-and-feel standards such as Motif and Presentation Manager. Different look-and-feels define different appearances and behaviors for user interface widgets like scrollbars, buttons, radio buttons etc… To be portable across different look-and-feels standards, an application should not hard code its widgets to a particular look-and-feel. It becomes difficult to change the look-and-feel at a later stage if we did so.

This problem can be solved by creating an abstract WidgetFactory class that declares an interface for creating a particular widget. There’s also an abstract class for every kind of widget whose subclasses provide the implementation for creating a widget of certain look-and-feel. Clients call the operations in the interface provided by WidgetFactory which returns an instance of the abstract widget class. Clients aren’t aware of the concrete classes they are using. Thus clients stay independent of the look-and-feel.

abstract factory pattern motivation

 

Applicability:

We should use Abstract Factory design pattern when:

  1. The system needs to be independent of the products it works with are created.
  2. The system should be configured to work with multiple families of products.
  3. A family of products is designed to be used together and this constraint is needed to be enforced.
  4. A library of products is to be provided and only their interfaces are to be revealed but not their implementations.

 

Examples where the Abstract Factory pattern can be used:

  • Phone numbers
  • Pizza factory
  • Look & feel

 

Structure:

abstract factory pattern structure

 

Participants:

The classes that participate in the Abstract Factory are:

AbstractFactory: Declares an interface of operations that create abstract products.

ConcreteFactory:  Implements operations to create concrete products.

AbstractProduct: Declares an interface for a type of product objects.

Product: Defines a product to be created by the corresponding ConcreteFactory. It implements the AbstractProduct interface.

Client: Uses the interfaces declared by the AbstractFactory and AbstractProduct classes.

 

Collaborations:

  • The ConcreteFactory class creates products objects having a particular implementation. To create different product, the client should use a different concrete factory.
  • AbstractFactory defers creation of product objects to its ConcreteFactory subclass.

 

Consequences:

Following are the benefits and liabilities of Abstract Factory pattern:

  1. It isolates concrete classes.
  2. It makes exchanging product families easy.
  3. It creates consistency among products.
  4. Supporting new kinds of products is difficult.

 

Implementation:

The AbstractFactory class is the one that determines the actual type of the concrete object and creates it, but it returns an abstract reference to the concrete object just created. This determines the behavior of the client that asks the factory to create an object of a certain abstract type and to return the abstract pointer to it, keeping the client from knowing anything about the actual creation of the object.

The fact that the factory returns an abstract pointer to the created object means that the client doesn’t have knowledge of the object’s type. This implies that there is no need for including any class declarations relating to the concrete type, the client deals at all times with the abstract type. The objects of the concrete type, created by the factory, are accessed by the client only through the abstract interface.

The second implication of this way of creating objects is that when adding new concrete types is needed, all we have to do is modify the client code and make it use a different factory, which is far easier than instantiating a new type, which requires changing the code wherever a new object is created.

The classic implementation for the Abstract Factory pattern is the following:

abstract class AbstractProductA 
{
	public abstract void operationA1();
	public abstract void operationA2();
}

class ProductA1 extends AbstractProductA 
{
	ProductA1(String arg)
	{
		System.out.println("Hello "+arg);
	} 
	// Implement the code here
	public void operationA1() { };
	public void operationA2() { };
}

class ProductA2 extends AbstractProductA 
{
	ProductA2(String arg)
	{
		System.out.println("Hello "+arg);
	} 
	// Implement the code here
	public void operationA1() { };
	public void operationA2() { };
}

abstract class AbstractProductB 
{
	public abstract void operationB1();
	public abstract void operationB2();
}

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
}

abstract class AbstractFactory 
{
	abstract AbstractProductA createProductA();
	abstract AbstractProductB createProductB();
}

class ConcreteFactory1 extends AbstractFactory 
{
	AbstractProductA createProductA()
	{
		return new ProductA1("ProductA1");
	}
	AbstractProductB createProductB()
	{
		return new ProductB1("ProductB1");
	}
}

class ConcreteFactory2 extends AbstractFactory 
{
	AbstractProductA createProductA()
	{
		return new ProductA2("ProductA2");
	}
	AbstractProductB createProductB()
	{
		return new ProductB2("ProductB2");
	}
}


//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
	}
}

 

Issues in implementation:

Factories as Singletons:

An application generally needs only one instance of the ConcreteFactory class per family product. It is best to implement that class as a Singleton.

 

Creating the products:

The AbstractFactory class only declares the interface for creating the products. It is the task of the ConcreteProduct class to actually create the products. For each family the best idea is applying the Factory Method design pattern. A concrete factory will specify its products by overriding the factory method for each of them. Even if the implementation might seem simple, using this idea will mean defining a new concrete factory subclass for each product family, even if the classes are similar in most aspects.

 

For simplifying the code and increase the performance the Prototype design pattern can be used instead of Factory Method, especially when there are many product families. In this case the concrete factory is initiated with a prototypical instance of each product in the family and when a new one is needed instead of creating it, the existing prototype is cloned. This approach eliminates the need for a new concrete factory for each new family of products.

 

Extending the factories:

The operation of changing a factory in order for it to support the creation of new products is not easy. What can be done to solve this problem is, instead of a CreateProduct method for each product, to use a single Create method that takes a parameter that identifies the type of product needed. This approach is more flexible, but less secure. The problem is that all the objects returned by the Create method will have the same interface, that is the one corresponding to the type returned by the Create method and the client will not always be able to correctly detect to which class the instance actually belongs.

 

Sample Code:

Let’s take the UI toolkit concept on to our Java code example. We’ll create a client application that needs to create a window.

First, we’ll need to create our Window interface. Window is our AbstractProduct.

//Our AbstractProduct 
public interface Window
{
	public void setTitle(String text);
    	public void repaint();
}

Let’s create two implementations of the Window, as our ConcreteProducts. One for Microsoft Windows:

//ConcreteProductA1
public class MSWindow implements Window
{
	public void setTitle()
	{
		//MS Windows specific behaviour 
	}
	public void repaint()
	{
		//MS Windows specific behaviour 
	}
}

And one for Mac OSX:

//ConcreteProductA2
public class MacOSXWindow implements Window
{
	public void setTitle()
	{
		//Mac OSX specific behaviour 
	}
	public void repaint()
	{
		//Mac OSX specific behaviour 
	}
}

Now we need to provide our factories. First we’ll define our AbstractFactory. For this example, let’s say they just create Windows:

//AbstractFactory 
public interface AbstractWidgetFactory 
{
	public Window createWindow();
}

Next we need to provide ConcreteFactory implementations of these factories for our two operating systems. First for MS Windows:

//ConcreteFactory1
public class MsWindowsWidgetFactory 
{
	//create an MSWindow 
	public Window createWindow()
	{
		MSWindow window = new MSWindow();   
		return window;
	}
}

And for MacOSX:

//ConcreteFactory2
public class MacOSXWidgetFactory 
{
	//create a MacOSXWindow 
	public Window createWindow()
	{
		MacOSXWindow window = new MacOSXWindow();   
		return window;
	}
}

Finally we need a client to take advantage of all this functionality.

//Client
public class GUIBuilder 
{
	public void buildWindow(AbstractWidgetFactory widgetFactory)
	{
		Window window = widgetFactory.createWindow();   
		window.setTitle("New Window");
	}
}

We need some way to specify which type of AbstractWidgetFactory to our GUIBuilder. This is usually done with a switch statement similar to the code below:

public class Main
{
	public static void main(String[] args)   
	{
		GUIBuilder builder = new GUIBuilder();
		AbstractWidgetFactory widgetFactory = null;
		//check what platform we're on 
		if(Platform.currentPlatform()=="MACOSX")
		{
			widgetFactory  = new MacOSXWidgetFactory();
		}
		else
		{
			widgetFactory  = new MsWindowsWidgetFactory();
		}
		builder.buildWindow(widgetFactory); 
	}
}

 

 

abstract factory pattern real world example

 

Known Uses:

  1. InterViews uses the “kit” suffix to denote AbstractFactory classes. It defines WidgetKit and DialogKit abstract factories to generate user interface objects.
  2. ET++ uses the Abstract Factory pattern to achieve portability across different window systems.

 

Related Patterns:

AbstractFactory classes are often implemented with factory methods but they can also be implemented using Prototype. A concrete factory is often a Singleton.

Example Abstract Factory classes in java API:

  • javax.xml.parsers.DocumentBuilderFactory
  • javax.xml.transform.TransformerFactory
  • javax.xml.xpath.XPathFactory

 

Non-software example:

The purpose of the Abstract Factory is to provide an interface for creating families of related objects, without specifying concrete classes. This pattern is found in the sheet metal stamping equipment used in the manufacture of Japanese automobiles. The stamping equipment is an Abstract Factory which creates auto body parts. The same machinery is used to stamp right hand doors, left hand doors, right front fenders, left front fenders, hoods etc. for different models of cars. Through the use of rollers to change the stamping dies, the concrete classes produced by the machinery can be changed within three minutes.

abstract factory pattern non software example

Suryateja Pericherla

Suryateja Pericherla

Hello, I am Suryateja Pericherla working as an Asst. Professor in CSE department at Vishnu Institute of Technology. I write articles to share my knowledge and make people knowledgeable regarding certain topics.
Suryateja Pericherla

Latest posts by Suryateja Pericherla (see all)

Note: Do you have a question on this article or have a suggestion to make this article better? You can ask or suggest us by filling in the below form. After commenting, your comment will be held for moderation and will be published in 24-48 hrs.
Scroll Up
Thank you for visiting startertutorials.com! If you like this website do share with your friends by clicking on the social icons available on the left hand side.

As the domain name is quite large to remember, use this short domain to visit this site. Short domain: stuts.me