팩토리 메서드 패턴이 제품을 생산하기 위한 것이라면
추상 팩토리 패턴은 제품을 구성하는 부품? 재료? 를 생산하기 위한 것이다.
Abstract Factory Pattern
제품을 구성하는 부품들 중 연관이 있는 것을 묶어 생산하는 것이 추상 팩토리 패턴의 핵심이다.
구체적으로는 제품을 구성하는 부품을 만드는 인터페이스를 정의하고
그 인터페이스에 따라 다양한 부품군을 생산하는 것이다.
interface VehiclePartFactory {
Engine createEngine();
Tire createtire();
List<Option> createOptions();
}
class CityVehiclePartFactory implements VehiclePartFactory {...}
class OffloadVehiclePartFactory implements VehiclePartFactory {...}
엔진, 타이어, 옵션들은 차량을 구성하는 부품으로 묶은 VehiclePartFactory 를 인터페이스로 정의하였고,
도심에 어울리는 차량의 부품을 생산하는 CityVehiclePartFactory
오프로드에 어울리는 차량의 부품을 생산하는 OffloadVehiclePartFactory
를 구현하였다.
이렇게 만들어진 부품 공장은 제품(차량)을 만들 때 의존성 주입을 통해 사용된다.
class SuperBus extends Vehicle {
private VehiclePartFactory vehiclePartFactory
public SuperBus(VehiclePartFactory vehiclePartFactory) {
this.vehiclePartFactory = vehiclePartFactory
}
public void assemble() {
engine = vehiclePartFactory.createEngine()
tire = vehiclePartFactory.createTire()
options = List.of()
}
}
SuperBus 를 도심용으로 생산하고 싶으면 CityVehiclePartFactory 를 주입하고
VehiclePartFactory 에서 생산하는 부품 중 사용할 부품만 가져와서 사용하면 된다.
위에서는 엔진과 타이어를 만들고 옵션이 없는 깡통 SuperBus 를 만들고 있다.
좀 귀찮은 부분이 모든 제품이 부품군 팩토리를 필드로 가져야 하는 것인데,
추상 클래스에 넣으면 해결 될 것 같으나 외부에 유출하고 싶지 않은 필드를 protected 로 만들어야 해서
캡슐화에 문제가 있다.
제품을 생산하는 공장에서는 제품에 필요한 부품군을 주입해 주면 된다.
class SuperVehicleFactory extends VehicleFactory {
protected Vehicle createVehicle(VehicleType vehicleType) {
return switch (vehicleType) {
case BUS -> new SuperBus(new CityVehiclePartFactory());
case TRUCK -> new SuperTruck(new OffloadVehiclePartFactory());
}
}
}
Abstract Factory Pattern Class Diagram
제품의 부품군을 생성하는 곳이 추상 팩토리 패턴의 핵심이므로, 제품을 생성하는 팩토리 메서드 패턴 부분은 제외하였다.
제품의 인터페이스가 Vehicle, 제품의 구상 클래스가 SuperBus, SuperTruck, UltraBus, UltraTruck,
제품에 필요한 부품군 팩토리의 인터페이스가 VehiclePartFactory,
부품군 팩토리의 구상 클래스가 CityVehiclePartFactory, OffloadVehiclePartFactory 이다.
CityVehiclePartFactory 는 도심용 차량 부품을 생산하는 공장이고,
OffloadVehiclePartFactory 는 오프로드용 차량 부품을 생산하는 공장이다.
제품은 필요한 부품군 공장을 주입받아 부품 생산을 부품군 공장에게 위임해서 받아 쓴다.
SuperBus 를 도심용 차량으로 생산하고 싶으면 CityVehiclePartFactory 를 주입받아, 도심용 차량 부품 생산을 위임하면 된다.
전체 소스는 https://github.com/Jongwon-Hyun/design_pattern
Factory Method Pattern VS. Abstract Factory Pattern
팩토리 메서드 패턴과 추상 팩토리 패턴의 가장 큰 차이는 확장을 통해 객체를 만드는가, 구성을 통해 객체를 만드는 가이다.
팩토리 메서드 패턴은 추상 공장 클래스를 확장한 구상 공장에서 제품을 생산하고,
추상 팩토리 패턴은 구성을 통해 제품에 주입되어 부품을 생산한다.
그리고 추상 팩토리 패턴에는 팩토리 메서드 패턴도 사용되고 있는데
실제로 부품을 만드는 것을 구상 클래스에 위임하고 있는 것이다.
// Factory Method Pattern
abstract class ProductFactory {
public abstract Product createProduct();
}
class AbcProducctFactory extends ProductFactory {
public Product createProduct() {
return Product;
}
}
// Abstract Factory Pattern
interfact PartFactory {
Part createPart();
}
class AbcPartFactory {
public Part createPart() {
return Part;
}
}
class Product {
private PartFactory partFactory;
// 부품군 팩토리 주입
public Product(PartFactory partFactory) {
this.partFactory = partFactory;
}
public assemble() {
part = partFactory.createPart();
}
}
'Programming > OOP' 카테고리의 다른 글
[Design Pattern] Command Pattern, 커맨드 패턴 (2) | 2022.05.06 |
---|---|
[Design Pattern] Singleton Pattern, 싱글톤 패턴 (0) | 2022.05.02 |
[Design Pattern] Factory Method Pattern, 팩토리 메서드 패턴 (0) | 2022.04.25 |
[Design Pattern] Decorator Pattern, 데코레이터 패턴 (0) | 2022.04.21 |
[Design Pattern] Observer Pattern, 옵저버 패턴 (0) | 2022.04.19 |
댓글