공통된 특징을 가지고 있는 객체의 패밀리를 생성하는 패턴으로 팩토리의 인터페이스를 정의하고 이후 서브 클래스에서 객체 패밀리를 생성하는 패턴이다.
밑의 추상 팩토리 패턴의 문제상황은 팩토리 메서드 패턴에서 사용한 문제상황과 유사하다. 패턴이름이 비슷하지만 다른 패턴이다.
1. Car를 만들기 위해서 Engine와 Wheel이 필요하다.
interface Engine {
void move();
}
interface Wheel {
void rotate();
}
2. Sedan을 만들기 위해서는 SedanEngine과 SedanWheel이 필요하다.
class SedanEngine implements Engine {
public void move() {
System.out.println("Moving Sedan Engine...");
}
}
class SedanWheel implements Wheel {
public void rotate() {
System.out.println("Rotating Sedan Wheel...");
}
}
3. SUV를 만들기 위해서는 SUVEngine과 SUVWheel이 필요하다.
class SUVEngine implements Engine {
public void move() {
System.out.println("Moving SUV Engine...");
}
}
class SUVWheel implements Wheel {
public void rotate() {
System.out.println("Rotating SUV Wheel...");
}
}
4. Sedan이나 SUV의 부품(Engine, Wheel)을 만드는 Client 코드는 다음과 같다.
public class Client {
public static void main(String[] args) {
Engine engine;
Wheel wheel;
String carType = "SUV";
if (carType.equals("Sedan")) {
engine = new SedanEngine();
wheel = new SedanWheel();
} else {
engine = new SUVEngine();
wheel = new SUVWheel();
}
engine.move();
wheel.rotate();
}
}
위 상황에서 Client는 각 Car에 해당하는 부품들을 직접 생성한다. 이러한 상황은 다음과 같은 문제가 발생한다.
위 두개의 상황 모두 Client 코드를 수정해야 하며 많아진다면 코드의 가독성이 크게 떨어진다.
부품을 생성하는 하나의 Factory를 정의하고 어떤 제품군을 생성할지는 서브클래스에서 결정하자
1. Engine, Wheel, CarFactory
interface Engine {
void move();
}
interface Wheel {
void rotate();
}
interface CarFactory {
Engine createEngine();
Wheel createWheel();
}
2. Sedan, SUV
class SedanEngine implements Engine {
public void move() {
System.out.println("Moving Sedan Engine...");
}
}
class SedanWheel implements Wheel {
public void rotate() {
System.out.println("Rotating Sedan Wheel...");
}
}
class SUVEngine implements Engine {
public void move() {
System.out.println("Moving SUV Engine...");
}
}
class SUVWheel implements Wheel {
public void rotate() {
System.out.println("Rotating SUV Wheel...");
}
}
구조의 ConcreteProduct에 해당한다.
3. SedanCarFactory, SUVCarFactory
class SedanCarFactory implements CarFactory {
public Engine createEngine() {
return new SedanEngine();
}
public Wheel createWheel() {
return new SedanWheel();
}
}
class SUVCarFactory implements CarFactory {
public Engine createEngine() {
return new SUVEngine();
}
public Wheel createWheel() {
return new SUVWheel();
}
}
각 Factory는 제품군에 맞는 ConcreteProduct를 생성한다.
3. Client
public class Client {
public static void main(String[] args) {
CarFactory carFactory;
String carType = "SUV";
if (carType.equals("Sedan")) {
carFactory = new SedanCarFactory();
} else {
carFactory = new SUVCarFactory();
}
Engine engine = carFactory.createEngine();
Wheel wheel = carFactory.createWheel();
engine.move();
wheel.rotate();
}
}
패턴이 적용된 상황에서 앞서 언급한 문제상황에 대해서 살펴보면 다음과 같다.
TruckCarFactory, TruckEngine, TruckWheel을 추가하면 된다.
interface Door와 이를 상속받는 SedanDoor와 SUVDoor를 추가하면 된다.