|Pattern Name||Abstract Factory Pattern|
|Pattern Type||Creational Pattern|
|Tagline||Factory of Factories|
|Use cases||When we need a factory to generate |
multiple factory pattern implementations
Using the Factory pattern we generate objects based on some criteria. In Abstract factory pattern, we use multiple factory pattern implementations and generate objects based on that.
Consider this as a Factory that generates other Factories. So factory pattern works as a subset of this pattern implementation.
The purpose of Abstract Factory pattern is to create family/group of related/dependent objects, without depending on their concrete classes. Abstract Factory pattern also provides an encapsulation to the group of individual factories.
Abstract factory pattern is also called Factory of Factories, so before reading about Abstract Factory Pattern, take a look at the Factory Pattern.
- When we need to handle multiple factories.
- When an implementation needs to be independent of the creation and representation of the item classes.
- When the item classes have different groups/families and those are supposed to be used and handled together.
- When we want to release a package of item classes, but don’t want to reveal the implementation (Would disclose the interface only).
- When we want to easily interchange factory classes(from a bunch of factory classes).
We need to implement multiple factory patterns and then implement a parent factory for those factory implementations.
There are 5 elements in the implementation:
- Abstract Factory Interface: interface that is implemented by concrete abstract factory classes.
- Concrete Abstract Factory Classes: classes that return instances of the concrete class.
- General Interface: interface implemented by concrete classes.
- Concrete Classes: classes implementing factory interface and containing the actual operations. Getting these classes is the final purpose of this implementation.
- Factory Producer: returns instances of concrete factory based on some pre-decided condition. Factory Producer directly uses only Abstract Factory Interface and Concrete Abstract Factory Classes.
Here is a diagram to represent the Abstract Factory Pattern implementation.
Here is how to implement Abstract Factory Pattern:
- First step is to create the classes that we want to use finally. These concrete classes are the main utility classes.
- Create an interface to standardize the utility classes.
- Implemented the interface to the utility classes.
- Create an interface for Abstract Factory and implement how the factory classes will be used to generate objects.
- Create multiple classes (as required) and implement Abstract factory and Use this parent factory to generate objects from the desired classes.
- Create a factory producer class, implement the condition to generate and return the factory class based on some conditions.
Example #1: Transport
Let’s take the example of a transport system. We have vehicles divided into 2 groups- Two wheelers and Four wheeler.
Take a look at the implementation.
Transport Factory Interface
Let’s create an interface for all the transport classes.
interface Transport function start() function stop() function repair() end interface
Transport Classes Implementing Transport Interface
Create transport item classes – Bicycle, Motorcycle, Car, Truck. All these classes implement the Transport interface.
// Bicycle class class Bicycle implements Transport function start() print "Bicycle Started" end function function stop() print "Bicycle Stopped" end function function repair() print "Bicycle Repair" end function end class // Motorcycle class class Motorcycle implements Transport function start() print "Motorcycle Started" end function function stop() print "Motorcycle Stopped" end function function repair() print "Motorcycle Repair" end function end class // Car class class Car implements Transport function start() print "Car Started" end function function stop() print "Car Stopped" end function function repair() print "Car Repair" end function end class // Truck class class Truck implements Transport function start() print "Truck Started" end function function stop() print "Truck Stopped" end function function repair() print "Truck Repair" end function end class
Abstract Transport Factory Interface
Let’s create an interface for the factory classes.
interface AbstractTransportFactory function getTransport(type: String): Transport end interface
Two-Wheel Transport Factory Class
Create a factory for two-wheeler vehicles and implement the AbstractTransportFactory interface.
class TwoWheelTransportFactory implements AbstractTransportFactory fuction getTransport(String type): Transport if (type == "bicycle") return new Bicycle() end if if (type == "motorcycle") return new Motorcycle() end if return null end function end class
Four-Wheel Transport Factory Class
Create a factory for four-wheeler vehicles and implement the AbstractTransportFactory interface.
class FourWheelTransportFactory implements AbstractTransportFactory function getTransport(type: String): Transport if (type == "car") return new Car() end if if (type == "truck") return new Truck() end if return null end function end class
Factory Producer Class
We need a class to generate those factory classes. Call that Factory Producer. This factory producer returns one of the above factories based on the number of wheels.
class FactoryProducer static function getFactory(int numberOfWheels): AbstractTransportFactory if (numberOfWheels == 2) return new TwoWheelTransportFactory() end if if (numberOfWheels == 4) return new FourWheelTransportFactory() end if return null end function end class
var transportFactory1: AbstractTransportFactory = FactoryProducer.getFactory(2) Transport transport1 = transportFactory1.getTransport("bicycle") transport1.start() var transportFactory2: AbstractTransportFactory = FactoryProducer.getFactory(4) Transport transport2 = transportFactory2.getTransport("truck") transport2.start()
Bicycle Started Truck Started
Use the following links to check Abstract Factory pattern implementation in specific programming languages.