생성패턴
팩토리 메서드 패턴은 생성 패턴에 속해 있다.
기존 코드의 유연성과 재사용을 증가시키는 다양한 객체 생성 메커니즘들을 제공
팩토리 메서드

문제
물류 관리 앱을 개발하는 상황을 예로 들어보겠습니다.
- 초기 버전에서는
트럭(Truck)
운송만 지원하며, 대부분의 코드는Truck
클래스에 의존합니다. - 이후 해상 물류 기능이 요구되면서
Ship
클래스를 추가해야 하지만, 기존 코드가Truck
클래스와 강하게 결합되어 있어 수정이 어렵습니다. - 새로운 운송이 추가될 때마다 조건문과 코드 수정이 반복되어 코드가 복잡해지고 유지보수가 어려워집니다.
이러한 문제점을 해결하기 위해 팩토리 메서드를 사용합니다.
의도
팩토리 메서드 패턴은 부모 클래스에서 객체를 생성할 수 있는 인터페이스를 제공하면서, 자식 클래스가 생성되는 객체의 구체적인 유형을 결정할 수 있도록 하는 생성 패턴입니다. 이 패턴은 객체 생성 로직을 캡슐화하여 코드의 유연성과 확장성을 높이는 데 사용됩니다.
동작 방식
팩토리 메서드 패턴은 new 연산자를 사용한 직접적인 객체 생성 대신, 팩토리 메서드를 호출하여 객체를 생성합니다.
객체는 여전히 new 연산자로 생성되지만, 이 호출은 팩토리 메서드 내부에서만 이루어집니다. 이를 통해 클라이언트 코드와 객체 생성 로직 간의 결합도를 낮출 수 있습니다.

(상속 관계에서는 자식 클래스는 오버라이딩을 통해 메서드를 변경할 수 있고, createTransport 메서드가 반환하는 객체의 클래스를 변경했다)
- Factory 추상 클래스는 객체 생성을 위한 팩토리 메서드(createTransport)를 선언합니다.
- LoadFactory는 Truck 객체를 반환하고, SeaFactory는 Ship 객체를 반환합니다.
- 클라이언트는 팩토리를 통해 운송 수단을 생성하며, 객체의 구체적인 클래스에 대해 알 필요가 없습니다.
이러한 변경은 처음에는 무의미해 보일 수 있습니다.
생성자 호출을 단순히 프로그램의 한 부분에서 다른 부분으로 옮긴 것 처럼 보일 수 있기 때문입니다.
그러나 이 변경 덕분에 자식 클래스에서 팩토리 메서드를 오버라이딩 하여 생성되는 객체의 유형을 유연하게 변경할 수 있습니다. 이는 코드의 수정 없이 새로운 제품 유형을 추가할 수 있는 확장성을 제공합니다.
다만 몇 가지 제한 사항이 있습니다.
팩토리 메서드가 반환할 수 있는 객체는 반드시 공통 기초 클래스나 공통 인터페이스를 구현해야 합니다.
예를 들어, 모든 제품(Truck, Ship)은 Transport
라는 공통 인터페이스를 구현해야 하며, 팩토리 기초 클래스의 createTransport
메서드도 이 인터페이스를 반환 타입으로 선언해야 합니다.

예를 들어 Truck과 Ship 클래스 모두 Transport 인터페이스를 구현해야 하며, 이 인터페이스는 deliver
메서드를 선언합니다.
하지만 각 클래스는 이 메서드의 구체적인 동작 방식을 다르게 구현합니다. 트럭은 육로로, 선박은 해상으로 물건을 배달합니다.
LoadFactory 클래스에 포함된 팩토리 메서드(createTransport)는 Truck을 반환하는 반면,
SeaFactory 클래스에 포함된 팩토리 메서드는 Ship을 반환합니다.
클라이언트 코드의 역할
클라이언트 코드는 팩토리 메서드를 호출하여 객체를 생성하지만, 구체적으로는 어떤 객체가 반환되는지는 알 필요가 없습니다. 모든 객체는 공통 인터페이스(Transport)에 정의된 메서드만 사용할 수 있습니다. 예를 들어 클라이언트가 deliver 메서드를 호출하면 트럭은 육로 배달을, 선박은 해상 배달을 수행하지만, 클라이언트는 이 동작의 세부 구현에 대해 몰라도 됩니다.
구조

- Product(공통 인터페이스)
- 모든 제품이 구현해야 할 공통 메서드를 정의합니다.
- Ex) Transport 인터페이스는 deliver 메서드를 선언합니다.
- ConcreteProduct(구체적인 제품)
- 공통 인터페이스를 구현하는 구체적인 클래스들입니다.
- Ex) Truck 클래스는 육로 배달을, Ship 클래스는 해상 배달을 구현합니다.
- Creator(추상 팩토리 클래스)
- 객체를 반환하는 팩토리 메서드를 선언합니다.
- 팩토리 메서드의 반환 타입은 공통 인터페이스와 일치해야 합니다.
- ConcreteCreator(구체적인 팩토리 클래스)
- 추상 팩토리 메서드를 오버라이딩 하여 특정 제품(Truck, Ship)을 반환합니다.
- LoadFactory는 트럭 객체를, SeaFactory는 선박 객체를 반환합니다.
적용
팩토리 메서드 패턴은 다음과 같은 경우에 적합합니다.
- 코드가 함께 작동해야 하는 객체의 정확한 유형이나 의존성을 미리 알 수 없을 때.
- 객체 생성 로직을 사용하는 코드와 분리하고 싶을 때
- 라이브러리나 프레임워크 사용자가 내부 컴포넌트를 확장할 수 있도록 설계할 때.
- 기존 객체를 재사용하거나 캐싱하여 리소스를 절약하고 싶을 때.
장점
- 유연한 확장성
- 기존 코드를 수정하지 않고 새로운 객체 생성 방식을 준수할 수 있다.(OCP)
- 객체 생성 책임을 하위 클래스에 위임하여 코드의 재사용성과 확장성을 높일 수 있다.
- 결합도 감소
- 객체 생성 로직과 사용 로직을 분리하여 Creator와 Product 간의 강한 결합을 막는다.
- 인터페이스를 통해 객체를 생성하므로 구현체에 대한 의존도를 줄이고 유지보수가 용이하다.
- 단일 책임 원칙 준수
- 객체 생성 로직이 별도의 팩토리 클래스에 집중되므로 각 클래스가 하나의 책임만 가지게 된다.
- 코드 일관성 및 관리 용이성
- 객체 생성을 한 곳에서 관리할 수 있어 코드의 가독성과 일관성이 향상된다.
단점
- 코드 복잡성 증가
- 초기 설계와 구현이 복잡해질 수 있으며, 단순한 객체 생성에는 오히려 과한 설계가 될 수 있다.
- 클래스 수 증가
- 새로운 유형이 추가될 때마다 해당 제품을 생성하는 팩토리 클래스를 추가해야 하므로 클래스 수가 급격히 증가할 수 있으며, 이는 클래스 구조의 복잡을 야기한다.
- 초기 설계 비용
- 패턴을 적용하기 위해 인터페이스와 추상 클래스를 설계해야 하므로 초기 개발 단계에서 시간이 더 소요될 수 있다.
정리
팩토리 메서드 패턴은 객체 생성 로직을 캡슐화하여 유지 보수성과 확정성을 높이는 데 유용합니다. 특히, 다양한 유형의 객체를 유연하게 추가할 수 있어 변화하는 요구사항에 대응하기 적합합니다. 하지만 필요 이상으로 복잡한 설계를 초래할 가능성이 있으므로 적절한 상황에서 사용하는것이 중요합니다.
참고
팩토리 메서드 패턴
/ 디자인 패턴들 / 생성 패턴 팩토리 메서드 패턴 다음 이름으로도 불립니다: 가상 생성자, Factory Method 의도 팩토리 메서드는 부모 클래스에서 객체들을 생성할 수 있는 인터페이스를 제공하지
refactoring.guru
'Computer Science > Design Pattern' 카테고리의 다른 글
[Design Pattern] - 디자인 패턴이란? (3) | 2024.12.31 |
---|
생성패턴
팩토리 메서드 패턴은 생성 패턴에 속해 있다.
기존 코드의 유연성과 재사용을 증가시키는 다양한 객체 생성 메커니즘들을 제공
팩토리 메서드

문제
물류 관리 앱을 개발하는 상황을 예로 들어보겠습니다.
- 초기 버전에서는
트럭(Truck)
운송만 지원하며, 대부분의 코드는Truck
클래스에 의존합니다. - 이후 해상 물류 기능이 요구되면서
Ship
클래스를 추가해야 하지만, 기존 코드가Truck
클래스와 강하게 결합되어 있어 수정이 어렵습니다. - 새로운 운송이 추가될 때마다 조건문과 코드 수정이 반복되어 코드가 복잡해지고 유지보수가 어려워집니다.
이러한 문제점을 해결하기 위해 팩토리 메서드를 사용합니다.
의도
팩토리 메서드 패턴은 부모 클래스에서 객체를 생성할 수 있는 인터페이스를 제공하면서, 자식 클래스가 생성되는 객체의 구체적인 유형을 결정할 수 있도록 하는 생성 패턴입니다. 이 패턴은 객체 생성 로직을 캡슐화하여 코드의 유연성과 확장성을 높이는 데 사용됩니다.
동작 방식
팩토리 메서드 패턴은 new 연산자를 사용한 직접적인 객체 생성 대신, 팩토리 메서드를 호출하여 객체를 생성합니다.
객체는 여전히 new 연산자로 생성되지만, 이 호출은 팩토리 메서드 내부에서만 이루어집니다. 이를 통해 클라이언트 코드와 객체 생성 로직 간의 결합도를 낮출 수 있습니다.

(상속 관계에서는 자식 클래스는 오버라이딩을 통해 메서드를 변경할 수 있고, createTransport 메서드가 반환하는 객체의 클래스를 변경했다)
- Factory 추상 클래스는 객체 생성을 위한 팩토리 메서드(createTransport)를 선언합니다.
- LoadFactory는 Truck 객체를 반환하고, SeaFactory는 Ship 객체를 반환합니다.
- 클라이언트는 팩토리를 통해 운송 수단을 생성하며, 객체의 구체적인 클래스에 대해 알 필요가 없습니다.
이러한 변경은 처음에는 무의미해 보일 수 있습니다.
생성자 호출을 단순히 프로그램의 한 부분에서 다른 부분으로 옮긴 것 처럼 보일 수 있기 때문입니다.
그러나 이 변경 덕분에 자식 클래스에서 팩토리 메서드를 오버라이딩 하여 생성되는 객체의 유형을 유연하게 변경할 수 있습니다. 이는 코드의 수정 없이 새로운 제품 유형을 추가할 수 있는 확장성을 제공합니다.
다만 몇 가지 제한 사항이 있습니다.
팩토리 메서드가 반환할 수 있는 객체는 반드시 공통 기초 클래스나 공통 인터페이스를 구현해야 합니다.
예를 들어, 모든 제품(Truck, Ship)은 Transport
라는 공통 인터페이스를 구현해야 하며, 팩토리 기초 클래스의 createTransport
메서드도 이 인터페이스를 반환 타입으로 선언해야 합니다.

예를 들어 Truck과 Ship 클래스 모두 Transport 인터페이스를 구현해야 하며, 이 인터페이스는 deliver
메서드를 선언합니다.
하지만 각 클래스는 이 메서드의 구체적인 동작 방식을 다르게 구현합니다. 트럭은 육로로, 선박은 해상으로 물건을 배달합니다.
LoadFactory 클래스에 포함된 팩토리 메서드(createTransport)는 Truck을 반환하는 반면,
SeaFactory 클래스에 포함된 팩토리 메서드는 Ship을 반환합니다.
클라이언트 코드의 역할
클라이언트 코드는 팩토리 메서드를 호출하여 객체를 생성하지만, 구체적으로는 어떤 객체가 반환되는지는 알 필요가 없습니다. 모든 객체는 공통 인터페이스(Transport)에 정의된 메서드만 사용할 수 있습니다. 예를 들어 클라이언트가 deliver 메서드를 호출하면 트럭은 육로 배달을, 선박은 해상 배달을 수행하지만, 클라이언트는 이 동작의 세부 구현에 대해 몰라도 됩니다.
구조

- Product(공통 인터페이스)
- 모든 제품이 구현해야 할 공통 메서드를 정의합니다.
- Ex) Transport 인터페이스는 deliver 메서드를 선언합니다.
- ConcreteProduct(구체적인 제품)
- 공통 인터페이스를 구현하는 구체적인 클래스들입니다.
- Ex) Truck 클래스는 육로 배달을, Ship 클래스는 해상 배달을 구현합니다.
- Creator(추상 팩토리 클래스)
- 객체를 반환하는 팩토리 메서드를 선언합니다.
- 팩토리 메서드의 반환 타입은 공통 인터페이스와 일치해야 합니다.
- ConcreteCreator(구체적인 팩토리 클래스)
- 추상 팩토리 메서드를 오버라이딩 하여 특정 제품(Truck, Ship)을 반환합니다.
- LoadFactory는 트럭 객체를, SeaFactory는 선박 객체를 반환합니다.
적용
팩토리 메서드 패턴은 다음과 같은 경우에 적합합니다.
- 코드가 함께 작동해야 하는 객체의 정확한 유형이나 의존성을 미리 알 수 없을 때.
- 객체 생성 로직을 사용하는 코드와 분리하고 싶을 때
- 라이브러리나 프레임워크 사용자가 내부 컴포넌트를 확장할 수 있도록 설계할 때.
- 기존 객체를 재사용하거나 캐싱하여 리소스를 절약하고 싶을 때.
장점
- 유연한 확장성
- 기존 코드를 수정하지 않고 새로운 객체 생성 방식을 준수할 수 있다.(OCP)
- 객체 생성 책임을 하위 클래스에 위임하여 코드의 재사용성과 확장성을 높일 수 있다.
- 결합도 감소
- 객체 생성 로직과 사용 로직을 분리하여 Creator와 Product 간의 강한 결합을 막는다.
- 인터페이스를 통해 객체를 생성하므로 구현체에 대한 의존도를 줄이고 유지보수가 용이하다.
- 단일 책임 원칙 준수
- 객체 생성 로직이 별도의 팩토리 클래스에 집중되므로 각 클래스가 하나의 책임만 가지게 된다.
- 코드 일관성 및 관리 용이성
- 객체 생성을 한 곳에서 관리할 수 있어 코드의 가독성과 일관성이 향상된다.
단점
- 코드 복잡성 증가
- 초기 설계와 구현이 복잡해질 수 있으며, 단순한 객체 생성에는 오히려 과한 설계가 될 수 있다.
- 클래스 수 증가
- 새로운 유형이 추가될 때마다 해당 제품을 생성하는 팩토리 클래스를 추가해야 하므로 클래스 수가 급격히 증가할 수 있으며, 이는 클래스 구조의 복잡을 야기한다.
- 초기 설계 비용
- 패턴을 적용하기 위해 인터페이스와 추상 클래스를 설계해야 하므로 초기 개발 단계에서 시간이 더 소요될 수 있다.
정리
팩토리 메서드 패턴은 객체 생성 로직을 캡슐화하여 유지 보수성과 확정성을 높이는 데 유용합니다. 특히, 다양한 유형의 객체를 유연하게 추가할 수 있어 변화하는 요구사항에 대응하기 적합합니다. 하지만 필요 이상으로 복잡한 설계를 초래할 가능성이 있으므로 적절한 상황에서 사용하는것이 중요합니다.
참고
팩토리 메서드 패턴
/ 디자인 패턴들 / 생성 패턴 팩토리 메서드 패턴 다음 이름으로도 불립니다: 가상 생성자, Factory Method 의도 팩토리 메서드는 부모 클래스에서 객체들을 생성할 수 있는 인터페이스를 제공하지
refactoring.guru
'Computer Science > Design Pattern' 카테고리의 다른 글
[Design Pattern] - 디자인 패턴이란? (3) | 2024.12.31 |
---|