추상 팩토리 패턴은 GoF 디자인 패턴의 생성 패턴 중 하나로, 서로 관련된 객체 군 여러 개를 묶어 인터페이스로 추상화하고 이를 구현하는 패턴이다!✨
쉽게 말해, 관련성이 있는 여러 객체들을 만들어주는 인터페이스 : 팩토리 클래스를 두고, 필요할 때 (구체적인 상황이 주어지면) 팩토리 클래스의 객체에서 묶은 객체군을 구현하는 것이다.
추상 팩토리 패턴도 구조도를 함께 볼 텐데, 이는 살짝 복잡할 수 있으니 구체적인 상황으로 추상 팩토리를 먼저 이해한 후 구조도를 살펴보자!
Builder 패턴에 관해 다룰 때, 잠깐 추상 팩도리를 다룬 적이 있다. 그 때의 설명을 빌리자면 다음과 같다.
(마우스, 키보드, 모니터로 이루어진) 컴퓨터를 제조할 건데, SamsungComputer와 LGComputer 중 어떤 것을 제조할지 입력 받아서 제조한다. 이 ComputerFactory는 삼성 또는 엘지를 입력 받아서 값에 따라 MouseFactory와 KeyboardFactory, MonitorFactory를 생성하고, 각 팩토리는 해당 회사의 마우스/키보드/모니터를 생성하는 것과 같다.
그런데 실제로 추상 팩토리 패턴을 공부해 보니, 다음의 비유가 좀 더 알맞겠다.
즉, 추상 팩토리는 공장 자체의 설계도이고, 구체적인 팩토리는 브랜드별 공장이다. 사용자는 어떤 공장을 사용할지 결정하기만 하면, 나머지는 그 공장이 알아서 처리한다.
(이 정도만 이해하면 추상 팩토리 패턴의 구조도 또한 한눈에 볼 수 있을 것이다!)
여기서 마우스 + 키보드 + 모니터처럼 서로 다르지만 연관이 있는 클래스를 묶어서 제품군이라 칭하고, 제품군을 정의하면 서로 연관된 객체들을 일관된 방식으로 생성할 수 있게 된다!

구조도의 윗부분부터 보자. 인터페이스(또는 추상 클래스)에 해당하는 AbstractFactory가 있다. 이는 createProductA()와 createProductB 메서드를 가진다. 이를 구현한 ConcreteFactory1, ConcreteFactory2 클래스는 동일하게 두 메서드를 구현해 실질적인 기능을 하는 클래스이다.
구조도의 맨 아래를 보면, AbstractFactory에서 메서드의 결과로 반환하는 Product를 정의한 AbstractProductA, AbstractProductB 클래스가 있다. 이 또한 AbstractFactory와 같이 실제 구현체가 아닌 인터페이스에 해당한다. 그리고 Factory와 마찬가지로, AbstractProduct를 구현한 ConcreteProductA1, B1, A1, B2가 존재한다. 이들은 ConcreteFactory1, 2에서 실제로 만들어내는 Product이다.
AbstractFactoryConcreteFactoryAbstractProductConcreteProduct
- 관련 제품의 다양한 제품 군과 함께 작동해야 할 때, 해당 제품의 구체적인 클래스에 의존하고 싶지 않은 경우
- 여러 제품군 중 하나를 선택해서 시스템을 설정해야 하고 한 번 구성한 제품을 다른 것으로 대체할 수도 있을 때
- 제품에 대한 클래스 라이브러리를 제공하고, 그들의 구현이 아닌 인터페이스를 노출시키고 싶을 때
구현은 앞서 예시로 들었던 모니터, 키보드, 마우스를 생산하는 컴퓨터 공장의 관계를 표현했고, 구조도에서 나타난 흐름을 그대로 적용했다!
추상 팩토리와 그 구현체를 보기 전에, 모니터, 키보드, 마우스를 나타낸 코드부터 보자!
→ 구조도와 비슷하게 추상 프로덕트 & 그 구현체로 나뉜 것을 볼 수 있다 :>
public interface AbstractKeyboard {}
public interface AbstractMonitor {}
public interface AbstractMouse {}
public class SamsungMonitor implements AbstractMonitor{}
public class SamsungKeyboard implements AbstractKeyboard{}
public class SamsungMouse implements AbstractMouse{}
public class LGMonitor implements AbstractMonitor{}
public class LGKeyboard implements AbstractKeyboard{}
public class LGMouse implements AbstractMouse{}
→ 구조도의 AbstractProduct와 그 구현체들을 나타낸다. AbstractKeyboard, AbstractMonitor, AbstractMouse라는 인터페이스가 있고, 이 추상적인 인터페이스를 실제 구현한 구현체가 있다. 예시로 들었던 Samsung과 LG의 모니터/키보드/마우스가 각각 있다.
public interface AbstractComputerFactory {
public AbstractMonitor createMonitor();
public AbstractKeyboard createKeyboard();
public AbstractMouse createMouse();
}
public class SamsungFactory implements AbstractComputerFactory{
public SamsungFactory() {
System.out.println("삼성 팩토리 생성");
}
@Override
public AbstractMonitor createMonitor() {
System.out.println("삼성 모니터 생성");
return new SamsungMonitor();
}
@Override
public AbstractKeyboard createKeyboard() {
System.out.println("삼성 키보드 생성");
return new SamsungKeyboard();
}
@Override
public AbstractMouse createMouse() {
System.out.println("삼성 마우스 생성");
return new SamsungMouse();
}
}
public class LGFactory implements AbstractComputerFactory{
public LGFactory() {
System.out.println("LG 팩토리 생성");
}
@Override
public AbstractMonitor createMonitor() {
System.out.println("LG 모니터 생성");
return new LGMonitor();
}
@Override
public AbstractKeyboard createKeyboard() {
System.out.println("LG 키보드 생성");
return new LGKeyboard();
}
@Override
public AbstractMouse createMouse() {
System.out.println("LG 마우스 생성");
return new LGMouse();
}
}
→ 추상팩토리에서 모니터 / 키보드 / 마우스를 제조하는 createMonitor(), createKeyboard(), createMouse() 메서드를 정의해 두었다. 그리고 그 구현체인 Samsung 팩토리와 LG 팩토리가 메서드들을 오버라이딩한다.
이제 팩토리를 실제로 생성해 제품들을 생산해 보자!
public class Main {
// 팩토리에서 모니터, 키보드, 마우스를 한 번에 생성
public static void create(AbstractComputerFactory computerFactory) {
computerFactory.createMonitor();
computerFactory.createKeyboard();
computerFactory.createMouse();
}
public static void main(String[] args) {
// 컴퓨터 팩토리 선언
AbstractComputerFactory computerFactory;
// computerFactory : 삼성 팩토리로 설정
computerFactory = new SamsungFactory();
create(computerFactory);
// computerFactory : LG 팩토리로 설정
computerFactory = new LGFactory();
create(computerFactory);
}
}
→ AbstractComputerFactory형 변수 computerFactory 하나만을 생성했다. 삼성 팩토리와 LG 팩토리를 설정한 다음의 코드를 보면, 서로 똑같은 create 메서드를 사용하고 있다. 하지만 출력 결과는 다음과 같다.
📌 출력 결과
삼성 팩토리 생성 삼성 모니터 생성 삼성 키보드 생성 삼성 마우스 생성 LG 팩토리 생성 LG 모니터 생성 LG 키보드 생성 LG 마우스 생성
→ 동일한 메서드들을 설정하더라도 오버라이딩된 메서드의 호출로 각 공장의 제품이 만들어지는 것을 확인할 수 있다.
→ 제품 군을 쉽게 대체할 수 있다는 추상 팩토리 패턴의 장점이 드러난다!👍
추상 팩토리 패턴은 제품군이라는 키워드가 핵심이라고 생각한다. 동일한 제품군으로 구성되는 무언가 (위 예시에선 컴퓨터) 를 하나의 추상 팩토리로 묶어두는 것이다! 따라서 구체적인 클래스에 의존하지 않고 인터페이스를 사용하며, 다른 구현체로 대체하는 것이 쉽다는 장점이 있으나, 같은 이유로 인터페이스 자체의 변경은 어려우므로 신중히 사용해야 할 듯하다!✌️