Abstract Factory Pattern
# Abstract Factory Pattern
The Abstract Factory Pattern is a creational design pattern that provides an interface for creating **families of related or dependent objects** without specifying their concrete classes. It is a "factory of factories".
In the Abstract Factory pattern, an interface is responsible for creating a family of related objects, without explicitly specifying their concrete classes. Each generated factory can provide objects according to the factory pattern.
The Abstract Factory pattern provides an interface for creating a series of related or interdependent objects without specifying their concrete implementation classes. By using the Abstract Factory pattern, the client can be decoupled from the creation process of specific products, allowing the client to create a family of products through the factory interface.
## Summary
### Intent
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
### Problem
The problem of interface selection.
### Use Case
When a system needs to create multiple related or dependent objects without specifying the concrete classes.
### Solution
Define multiple products within a product family, and the concrete factories implement the methods to create these products.
### Key Code
Aggregate the creation methods for multiple products of the same type in one factory.
### Real-World Analogy
Consider different types of wardrobes. Each wardrobe (concrete factory) can only store one type of clothing (a set of concrete products), such as business attire, fashion attire, etc. Each set of clothing includes specific shirts and pants (concrete products). All wardrobes are concrete implementations of the wardrobe class (abstract factory), and all shirts and pants implement the shirt interface and pants interface (abstract products), respectively.
### Pros
1. Ensures that objects from the same product family work together.
2. The client does not need to know the concrete class of each object, simplifying the code.
### Cons
Extending product families is very difficult. Adding a new product family requires modifying the code of the abstract factory and all concrete factories.
### Usage Scenarios
1. When changing skins in QQ, the entire skin set is changed together.
2. When creating cross-platform applications, generating programs for different operating systems.
### Note
Adding new product families is relatively easy, while adding new product hierarchies is more difficult.
### Structure
The Abstract Factory pattern includes the following main roles:
* **Abstract Factory**: Declares a set of methods for creating product objects. Each method corresponds to a product type. The abstract factory can be an interface or an abstract class.
* **Concrete Factory**: Implements the abstract factory interface and is responsible for creating instances of concrete product objects.
* **Abstract Product**: Defines a common interface or abstract class for a set of product objects, describing the common methods of the product objects.
* **Concrete Product**: Implements the abstract product interface, defining the specific behavior and properties of the concrete product.
The Abstract Factory pattern typically involves a family of related products. Each concrete factory class is responsible for creating the concrete products in that family. The client uses the abstract factory interface to create product objects without needing to directly use the implementation classes of the concrete products.
## Implementation
We will create the _Shape_ and _Color_ interfaces and the entity classes that implement these interfaces. The next step is to create the abstract factory class _AbstractFactory_. Then define the factory classes _ShapeFactory_ and _ColorFactory_, both of which extend _AbstractFactory_. Then create a factory creator/builder class _FactoryProducer_.
The _AbstractFactoryPatternDemo_ class uses _FactoryProducer_ to get the _AbstractFactory_ object. It will pass the shape information _Shape_ (_CIRCLE / RECTANGLE / SQUARE_) to the _AbstractFactory_ to get the type of object it needs. It also passes the color information _Color_ (_RED / GREEN / BLUE_) to the _AbstractFactory_ to get the type of object it needs.
[](#)
### Step 1
Create an interface for shapes.
## Shape.java
public interface Shape{void draw(); }
### Step 2
Create entity classes that implement the interface.
_Rectangle.java_
## Rectangle.java
public class Rectangle implements Shape{ @Override public void draw(){System.out.println("Inside Rectangle::draw() method."); }}
## Square.java
public class Square implements Shape{ @Override public void draw(){System.out.println("Inside Square::draw() method."); }}
## Circle.java
public class Circle implements Shape{ @Override public void draw(){System.out.println("Inside Circle::draw() method."); }}
### Step 3
Create an interface for colors.
## Color.java
public interface Color{void fill(); }
### Step 4
Create entity classes that implement the interface.
## Red.java
public class Red implements Color{ @Override public void fill(){System.out.println("Inside Red::fill() method."); }}
## Green.java
public class Green implements Color{ @Override public void fill(){System.out.println("Inside Green::fill() method."); }}
## Blue.java
public class Blue implements Color{ @Override public void fill(){System.out.println("Inside Blue::fill() method."); }}
### Step 5
Create an abstract class for Color and Shape objects to get the factory.
## AbstractFactory.java
public abstract class AbstractFactory{public abstract Color getColor(String color); public abstract Shape getShape(String shape); }
### Step 6
Create factory classes that extend AbstractFactory to generate objects of entity classes based on given information.
## ShapeFactory.java
public class ShapeFactory extends AbstractFactory{ @Override public Shape getShape(String shapeType){if(shapeType == null){return null; }if(shapeType.equalsIgnoreCase("CIRCLE")){return new Circle(); }else if(shapeType.equalsIgnoreCase("RECTANGLE")){return new Rectangle(); }else if(shapeType.equalsIgnoreCase("SQUARE")){return new Square(); }return null; } @Override public Color getColor(String color){return null; }}
## ColorFactory.java
public class ColorFactory extends AbstractFactory{ @Override public Shape getShape(String shapeType){return null; } @Override public Color getColor(String color){if(color == null){return null; }if(color.equalsIgnoreCase("RED")){return new Red(); }else if(color.equalsIgnoreCase("GREEN")){return new Green(); }else if(color.equalsIgnoreCase("BLUE")){return new Blue(); }return null; }}
### Step 7
Create a factory creator/builder class to get the factory by passing shape or color information.
## FactoryProducer.java
public class FactoryProducer{public static AbstractFactory getFactory(String choice){if(choice.equalsIgnoreCase("SHAPE")){return new ShapeFactory(); }else if(choice.equalsIgnoreCase("COLOR")){return new ColorFactory(); }return null; }}
### Step 8
Use FactoryProducer to get AbstractFactory, and get the object of the entity class by passing type information.
## AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo{public static void main(String[]args){//Get the shape factory AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //Get the object with shape Circle as Shape shape1 = shapeFactory.getShape("CIRCLE"); //Call the draw method of Circle shape1.draw(); //Get the object with shape Rectangle as Shape shape2 = shapeFactory.getShape("RECTANGLE"); //Call the draw method of Rectangle shape2.draw(); //Get the object with shape Square as Shape shape3 = shapeFactory.getShape("SQUARE"); //Call the draw method of Square shape3.draw(); //Get the color factory AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //Get the object with color Red as Color color1 = colorFactory.getColor("RED"); //Call the fill method of Red color1.fill(); //Get the object with color Green as Color color2 = colorFactory.getColor("GREEN"); //Call the fill method of Green color2.fill(); //Get the object with color Blue as Color color3 = colorFactory.getColor("BLUE"); //Call Blue's fill method color3.fill(); }}
### Step 9
Execute the program, output the result:
Inside Circle::draw() method.Inside Rectangle::draw() method.Inside Square::draw() method.Inside Red::fill() method.Inside Green::fill() method.Inside Blue::fill() method.
YouTip