객체 지향 프로그래밍에서 new 키워드를 사용하여 객체를 직접 생성하는 것은 가장 흔한 작업이지만, 동시에 강한 결합(Coupling) 을 유발하는 원인이기도 합니다.
Java
// 나쁜 예: 클라이언트가 구체적인 클래스에 의존함
Car car = new Sonata();
이 결합도를 낮추기 위해 "객체 생성을 전담하는 공장(Factory)" 을 만드는 것이 팩토리 패턴의 핵심입니다. 하지만 팩토리 패턴은 구현 복잡도에 따라 크게 3단계로 나뉩니다. 오늘은 그 차이를 명확히 정리해 보겠습니다.
1. 심플 팩토리 (Simple Factory)
엄밀히 말하면 GoF 디자인 패턴에는 포함되지 않는 관용구(Idiom)지만, 실무에서 가장 많이 쓰입니다. 단순히 객체 생성 로직을 별도의 클래스로 떼어낸 형태입니다.
특징
- static 메서드를 사용하여 입력값에 따라 다른 객체를 반환합니다.
- 클라이언트는 팩토리 클래스 하나만 알면 됩니다.
코드 예시
Java
public class CarFactory {
// static 메서드로 간단하게 구현
public static Car createCar(String type) {
if ("SONATA".equals(type)) {
return new Sonata();
} else if ("GRANDEUR".equals(type)) {
return new Grandeur();
}
throw new IllegalArgumentException("Unknown car type");
}
}
// 사용 (Client)
Car myCar = CarFactory.createCar("SONATA");
장단점
- 장점: 구현이 매우 쉽고, 클라이언트 코드가 깔끔해집니다.
- 단점: 새로운 차종(Genesis)이 추가되면 CarFactory의 if-else 문을 수정해야 하므로 OCP(개방-폐쇄 원칙)를 위반합니다.
2. 팩토리 메서드 패턴 (Factory Method Pattern)
GoF에서 정의하는 정석적인 패턴입니다. **"객체 생성을 서브 클래스에게 위임"**하는 방식입니다.
특징
- 부모 클래스(인터페이스)는 "객체를 생성한다"는 메서드(create)만 정의하고, 실제 어떤 객체를 만들지는 자식 클래스가 결정합니다.
- 상속(Inheritance) 구조를 활용합니다.
코드 예시
Java
// 1. 추상 팩토리 (Creator)
public abstract class CarFactory {
// 팩토리 메서드 (구현은 자식이 함)
abstract Car createCar();
// 공통 로직 (템플릿 메서드처럼 활용 가능)
public void deliverCar() {
Car car = createCar();
car.drive();
}
}
// 2. 구체적 팩토리 (Concrete Creator)
public class SonataFactory extends CarFactory {
@Override
Car createCar() {
return new Sonata();
}
}
public class GenesisFactory extends CarFactory {
@Override
Car createCar() {
return new Genesis();
}
}
장단점
- 장점: 새로운 차종이 추가되어도 기존 코드를 수정할 필요 없이 GenesisFactory만 새로 만들면 됩니다. (OCP 준수)
- 단점: 관리해야 할 클래스 파일의 개수가 늘어납니다.
3. 추상 팩토리 패턴 (Abstract Factory Pattern)
가장 복잡한 형태입니다. 단순히 객체 하나가 아니라, **"관련된 객체들의 집합(Family)"**을 생성해야 할 때 사용합니다.
상황 예시
- 윈도우(Windows) 스타일: WinButton, WinScrollbar
- 맥(Mac) 스타일: MacButton, MacScrollbar
- 이 부품들은 서로 섞이면 안 되고 세트로 다녀야 합니다.
코드 예시
Java
// 1. 추상 팩토리 (모든 부품을 만드는 공장 인터페이스)
public interface GUIFactory {
Button createButton();
Scrollbar createScrollbar();
}
// 2. 윈도우용 공장
public class WindowsFactory implements GUIFactory {
public Button createButton() { return new WinButton(); }
public Scrollbar createScrollbar() { return new WinScrollbar(); }
}
// 3. 맥용 공장
public class MacFactory implements GUIFactory {
public Button createButton() { return new MacButton(); }
public Scrollbar createScrollbar() { return new MacScrollbar(); }
}
장단점
- 장점: 제품군(Family) 간의 교체가 매우 쉽습니다. (new WindowsFactory()를 new MacFactory()로만 바꾸면 모든 UI가 변경됨)
- 단점: 새로운 부품 종류(예: TextField)가 추가되면, 모든 Factory 인터페이스와 구현체를 수정해야 하는 대공사가 일어납니다.
요약: 어떤 팩토리를 선택해야 할까?
| 패턴 종류 | 핵심 개념 | 구현 방식 | 추천 상황 |
| Simple Factory | 생성 로직 캡슐화 | static 메서드 + if-else | 생성할 객체 종류가 적고 변경이 거의 없을 때 |
| Factory Method | 생성 책임 위임 | 추상 메서드 + 상속 | 객체 생성 로직을 확장 가능하게(OCP) 만들고 싶을 때 |
| Abstract Factory | 제품군(Family) 생성 | 인터페이스 + 조합 | OS별 테마, DB별 접속 모듈 등 관련된 객체들을 한 번에 바꿔야 할 때 |
결론
대부분의 실무 비즈니스 로직에서는 Simple Factory나 Factory Method 선에서 해결되는 경우가 많습니다.
- Spring Framework를 사용하신다면 BeanFactory나 ApplicationContext가 이미 팩토리 패턴의 거대한 구현체입니다.
- 직접 구현할 때는 무조건 복잡한 추상 팩토리를 쓰기보다, Simple Factory로 시작해서 필요할 때 Factory Method로 리팩토링하는 접근을 추천합니다.
'프로그래밍 > 디자인패턴' 카테고리의 다른 글
| 프록시 패턴(Proxy Pattern) (0) | 2025.12.07 |
|---|---|
| 옵저버 패턴 vs Pub/Sub 패턴 (0) | 2025.12.07 |
| 싱글톤 패턴(Singleton Pattern) 완벽 정리 (0) | 2025.12.07 |
| 전략 패턴(Strategy Pattern) 완벽 정리 (0) | 2025.12.07 |
| 사가(Saga) 패턴이란? (0) | 2025.03.15 |