Both of these design patterns belong to the category of creational patterns, meaning they are used to provide object creation mechanisms which increase flexibility and reuse of existing code.
## Factory Method pattern
The Factory Method pattern is a creational pattern that defines an interface for creating an object, but allows subclasses to choose which class to instantiate. It provides a way for a class to delegate the instantiation of objects to subclasses.
In the Factory Method pattern, we define a factory method in an interface or an abstract class, which returns an object of a different class. The implementation of the factory method can be overridden in the subclass, which decides the specific class for object instantiation.
Here is an example of the Factory Method pattern in Java:
// A product interface
interface Product {
void use();
}
// Concrete products
class ConcreteProduct1 implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProduct1");
}
}
class ConcreteProduct2 implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProduct2");
}
}
// Abstract creator
abstract class Creator {
public void someOperation() {
Product product = createProduct();
product.use();
}
protected abstract Product createProduct();
}
// Concrete creators
class ConcreteCreator1 extends Creator {
@Override
protected Product createProduct() {
return new ConcreteProduct1();
}
}
class ConcreteCreator2 extends Creator {
@Override
protected Product createProduct() {
return new ConcreteProduct2();
}
}
// Usage
public class FactoryMethodDemo {
public static void main(String[] args) {
Creator creator1 = new ConcreteCreator1();
creator1.someOperation();
Creator creator2 = new ConcreteCreator2();
creator2.someOperation();
}
}
In this example, we have a ‘Product‘ interface and two concrete implementation classes, ‘ConcreteProduct1‘ and ‘ConcreteProduct2‘. We also have an abstract ‘Creator‘ class which defines the factory method ‘createProduct()‘ and the method ‘someOperation()‘. The concrete creator classes ‘ConcreteCreator1‘ and ‘ConcreteCreator2‘ override the ‘createProduct()‘ method to return an instance of the corresponding ‘ConcreteProduct‘.
## Abstract Factory pattern
The Abstract Factory pattern is also a creational pattern, which provides an interface for creating families of related or dependent objects, without specifying their concrete classes. It enables the creation of objects that are from the same family or group, which have some similarities and interdependencies.
In the Abstract Factory pattern, the client code does not specify which concrete implementation to use, instead it calls methods from the abstract factory interface to create the family of related objects. The implementation of these methods is provided by the concrete factory classes that implement the abstract factory interface.
Here is an example of the Abstract Factory pattern in Java:
// Abstract product A
interface AbstractProductA {
void use();
}
// Concrete product A1
class ConcreteProductA1 implements AbstractProductA {
@Override
public void use() {
System.out.println("Using ConcreteProductA1");
}
}
// Concrete product A2
class ConcreteProductA2 implements AbstractProductA {
@Override
public void use() {
System.out.println("Using ConcreteProductA2");
}
}
// Abstract product B
interface AbstractProductB {
void interact(AbstractProductA a);
}
// Concrete product B1
class ConcreteProductB1 implements AbstractProductB {
@Override
public void interact(AbstractProductA a) {
System.out.println("Interacting with ConcreteProductA1");
a.use();
}
}
// Concrete product B2
class ConcreteProductB2 implements AbstractProductB {
@Override
public void interact(AbstractProductA a) {
System.out.println("Interacting with ConcreteProductA2");
a.use();
}
}
// Abstract factory
interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// Concrete factory 1
class ConcreteFactory1 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
// Concrete factory 2
class ConcreteFactory2 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
// Usage
public class AbstractFactoryDemo {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
AbstractProductA productA1 = factory1.createProductA();
AbstractProductB productB1 = factory1.createProductB();
productB1.interact(productA1);
AbstractFactory factory2 = new ConcreteFactory2();
AbstractProductA productA2 = factory2.createProductA();
AbstractProductB productB2 = factory2.createProductB();
productB2.interact(productA2);
}
}
In this example, we have two abstract product interfaces ‘AbstractProductA‘ and ‘AbstractProductB‘ and four concrete product classes ‘ConcreteProductA1‘, ‘ConcreteProductA2‘, ‘ConcreteProductB1‘, and ‘ConcreteProductB2‘. We also have an abstract factory interface ‘AbstractFactory‘ with two factory methods ‘createProductA()‘ and ‘createProductB()‘. The concrete factory classes ‘ConcreteFactory1‘ and ‘ConcreteFactory2‘ implement the factory methods to return instances of the corresponding concrete product classes.
## Differences
So, to summarize the differences between the Factory Method and Abstract Factory patterns:
- Factory Method creates a single product, while Abstract Factory creates multiple related products.
- Factory Method uses inheritance to delegate instantiation to subclasses, while Abstract Factory uses composition to delegate instantiation to another object.
- Factory Method provides a way to encapsulate a specific algorithm for object creation, while Abstract Factory provides a way to encapsulate object creation for a group of related products.