추상 팩토리 패턴이란?
서로 관련이 있는 객체들을 통째로 묶어서 팩토리 클래스로 만들고, 이들 팩토리를 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성하는 패턴
관련성있는 여러 종류의 객체를 일관성 있는 방식으로 생성할 때 유용
- AbstractFactory: 실제 팩토리 클래스의 공통 인터페이스. 각 제품의 부품을 생성하는 기능을 추상 메서드로 정의
- ConcreteFactory: 구체적인 팩토리 클래스로 AbstractFactory 클래스의 추상 메서드를 오버라이드 함으로써 구체적인 제품 생성
- AbstractProduct: 제품의 공통 인터페이스
- ConcreteProduct: 구체적인 팩토리 클래스에서 생성되는 구체적인 제품
추상 팩토리 패턴 구현
교재 예시 : 엘리베이터 부품 업체 변경
- 엘리베이터 부품중 모터와 문
- 추상클래스로 Motor를 정의, LGMotor 와 HyundaiMotor를 하위 클래스
- 추상클래스로 Door 정의, LGDoor 와 HyundaiDoor를 하위 클래스
- 모터 구동 단계: 이미 이동중이면 무시 → 문이 열려있으면 문 닫기 → 모터를 구동해서 이동 → 모터의 상태를 이동중으로 설정
public abstract class Door {
private DoorStatus doorStatus;
public DoorStatus getDoorStatus(){
return doorStatus;
}
public void close() { //템플릿 메서드
if(doorStatus == DoorSatus.CLOSED)
return;
doClose(); //실제로 문 닫는 동작 수행 (하위 클래스에서 오버라이드)
doorStatus = DoorStatus.CLOSED;
}
protected abstract void doClose();
public void open(){
if(doorStatus == DoorStatus.OPENED)
return;
doOpen(); //실제로 문 여는 동작 수행 (하위 클래스에서 오버라이드)
doorStatus = DoorStatus.OPENED;
}
protected abstract void doOpen();
}
public class LGDoor extends Door {
protected void doClose(){
System.out.println("close LG Door");
}
protected void doOpen(){
System.out.println("open LG Door");
}
}
public class HyundaiDoor extends Door {
protected void doClose(){
System.out.println("close Hyundai Door");
}
protected void doOpen(){
System.out.println("open Hyundai Door");
}
}
public enum VendorId {LG, HYUNDAI}
public class MotorFactory { //팩토리 메서드 패턴 사용
public static Motor createMotor(VendorId vendorID){
Motor motor = null;
switch (vendorID){
case LG:
motor = new LGMotor();
break;
case HYUNDAI:
motor = new HyundaiMotor();
break;
}
return motor;
}
}
문제점
- 만약 다른 제조 업체의 부품을 사용해야한다면?
- 새로운 제조 업체의 부품을 지원해야한다면?
팩토리 메소드 패턴을 이용한 객체 생성은 관련있는 여러 개의 객체를 일관성 있는 방식으로 생성하는 경우, 많은 코드 변경이 발생
해결책
추상 팩토리 패턴 구현 : 여러 종류의 객체를 생성할 때, 객체들 사이에 일관성이 있는 경우, 관련 객체들을 일관성 있게 생성하는 Factory 클래스를 사용
- ex) 엘리베이터 프로그램의 경우, MotorFactory, DoorFactory 클래스와 같이 부품별로 Factory 클래스를 만드는 대신, LGElevatorFactory 나 HyundaiElevatorFactory 클래스와 같이 제조 업체별로 Factory 클래스 만들 수 있음.
public abstract class ElevatorFactory {
public abstract Motor createMotor();
public abstract Door createDoor();
}
public class LGElevatorFactory extends ElevatorFactory { // LG 부품을 생성하는 팩토리
public Motor createMotor(){
return new LGMotor();
}
public Door createDoor(){
return new LGDoor();
}
}
public class HyundaiElevatorFactory extends ElevatorFactory { // 현대 부품을 생성하는 팩토리
public Motor createMotor(){
return new HyundaiMotor();
}
public Door createDoor(){
return new HyundaiDoor();
}
}
public class ElevatorFactoryFactory { // 팩토리 클래스에 팩토리 메서드 패턴을 적용
public static ElevatorFactory getFactory(VendorID vendorID){
ElevatorFactory factory = null;
switch(vendorID){
case LG:
factory = LGElevatorFactory.getInstance();
break;
case HYUNDAI:
factory = HyundaiElevatorFactory.getInstance();
break;
case SAMSUNG:
factory = SaunsungElevatorFactory.getInstance();
break;
}
return factory;
}
}
public class LGElevatorFactory extends ElevatorFactory { // 싱글턴 패턴 적용한 LG 팩토리
private static ElevatorFactory factory;
private LGElevatorFactory(){}
public static ElevatorFactory getInstance(){
if(factory == null)
factory = new LGElevatorFactory();
return factory;
}
public Motor createMotor(){
return new LGMotor();
}
public Door createDoor(){
return new LGDoor();
}
}
public class Client {
public static void main(String args[]){
String vendorName = args[0];
VendorId vendorID;
if (vendorName.equalsIgnoreCase("LG"))
vendorID = VendorID.LG;
else if (vendorName.equalsIsIgnoreCase("Sansung"))
vendorID = VendorID.SANSUNG;
else
vendorID = VendorID.HYUNDAI;
ElevatorFactory factory = ElevatorFactoryFactory.getFactory(vendorID);
Door door = factory.createDoor();
Motor motor = factory.createMotor();
motor.setDoor(door);
door.open();
motor.move(Direction.UP);
}
}
Client 객체는 ConcreteFactory의 변화에 의해 영향을 받지 않을 수 있다
'Design pattern' 카테고리의 다른 글
[Desigan Pattern] Factory Method Pattern (0) | 2022.08.17 |
---|---|
[Design Pattern] Template Method Pattern (0) | 2022.08.14 |
[Design Pattern] Decorator Pattern (0) | 2022.08.10 |
[Design Pattern] Observer Pattern (0) | 2022.08.04 |
[Design Pattern] Command Pattern (0) | 2022.08.01 |