Intent
Provide an
interface for creating families of related or dependent objects without specifying
their concrete classes.
Motivation
Abstract
Factory patterns work around a super-factory which creates other factories. This factory is also called as factory of
factories and comes under Creational pattern. The abstract factory pattern
provides a way to encapsulate a group of individual factories that have a
common theme without specifying their concrete classes.
In
normal usage, the client software creates a concrete implementation of the
abstract factory and then uses the generic interface of the factory to create
the concrete objects that are part of the theme. The client doesn't know which
concrete objects it gets from each of these internal factories, since it uses
only the generic interfaces of their products.
This
pattern separates the details of implementation of a set of objects from their
general usage and relies on object composition, as object creation is
implemented in methods exposed in the factory interface.
Applicability
Use
the Abstract Factory pattern when
Ø A
system should be independent of how its products are created, composed, and
represented.
Ø A
system should be configured with one of multiple families of products.
Ø A
family of related product objects is designed to be used together, and you need
to enforce this constraint.
Ø You
want to provide a class library of products, and you want to reveal just their
interfaces, not their implementations.
Consequences
The Abstract
Factory pattern has the following benefits and liabilities:
Ø It isolates concrete classes. The Abstract
Factory pattern helps you control the classes of objects that an application
creates.
Ø It makes exchanging product families easy. The
class of a concrete factory appears only once in an application—that is, where
it's instantiated.
Ø It promotes consistency among products. When
product objects in a family are designed to work together, it's important that
an application use objects from only one family at a time.
Ø Supporting new kinds of products is difficult.
Extending abstract factories to produce new kinds of Products isn't easy.
Implementation
1. Create a class Car
public abstract class Car {
public abstract String
getHorsePower();
public abstract String
getSeatingCapacity();
public abstract String
getMileage();
@Override
public String
toString() {
return "Horse
Power : " + this.getHorsePower() +
",
Seating Capacity : "+this.getSeatingCapacity()
+
",
Mileage : "+this.getMileage();
}
}
|
2. Create sub class Sedan of class Car
public class Sedan extends Car{
private String horsePower;
private String seatingCapacity;
private String mileage;
public Sedan(String horsePower, String seatingCapacity, String mileage) {
this.horsePower = horsePower;
this.seatingCapacity = seatingCapacity;
this.mileage = mileage;
}
@Override
public String
getHorsePower() {
return this.horsePower;
}
@Override
public String
getSeatingCapacity() {
return this.seatingCapacity;
}
@Override
public String
getMileage() {
return this.mileage;
}
}
|
3. Create another sub class SUV of class Car
public class SUV extends Car{
private String horsePower;
private String seatingCapacity;
private String mileage;
public SUV(String horsePower, String seatingCapacity, String mileage) {
super();
this.horsePower = horsePower;
this.seatingCapacity = seatingCapacity;
this.mileage = mileage;
}
@Override
public String
getHorsePower() {
return this.horsePower;
}
@Override
public String
getSeatingCapacity() {
return this.seatingCapacity;
}
@Override
public String
getMileage() {
return this.mileage;
}
}
|
4. Create Abstract factory interface (Notice that the createCar() method returns
an instance of super class Car)
public interface
CarAbstractFactory {
public Car
createCar();
}
|
5. Now we will create Factory class for Each sub
class i.e SedanFactory and SUVFactory class
public class SedanFactory implements
CarAbstractFactory{
private String horsePower;
private String seatingCapacity;
private String mileage;
public
SedanFactory(String horsePower, String seatingCapacity, String mileage) {
this.horsePower = horsePower;
this.seatingCapacity = seatingCapacity;
this.mileage = mileage;
}
@Override
public Car
createCar() {
return new Sedan(horsePower,seatingCapacity,mileage);
}
}
|
public class SUVFactory implements
CarAbstractFactory{
private String horsePower;
private String seatingCapacity;
private String mileage;
public
SUVFactory(String horsePower, String seatingCapacity, String mileage) {
this.horsePower = horsePower;
this.seatingCapacity = seatingCapacity;
this.mileage = mileage;
}
@Override
public Car
createCar() {
return new SUV(horsePower,seatingCapacity,mileage);
}
}
|
6. Create a class that will provide the entry
point for the client classes to create sub-classes.
public class CarFactory {
public static Car
getCar(CarAbstractFactory factory){
return factory.createCar();
}
}
|
7. Write a class with the main() to test your
code.
public class Main {
public static void main(String[]
args) {
Car sedan=CarFactory.getCar(new SedanFactory("2.2", "5", "15
KMPL"));
System.out.println("Details
of Sedan : "+sedan);
Car suv=CarFactory.getCar(new SUVFactory("3.5", "07", "12
KMPL"));
System.out.println("Details
of SUV : "+suv);
}
}
|
We will get the following output.
|
Abstract Factory Design Pattern |