

추상 팩토리 정리
DesignPattern
2025.10.20.
추상 팩토리 패턴
1. 패턴 소개
- 관련 있는 여러 인스턴스를 만들어 주는 팩토리를 추상화된 형태로 정의하는 형태
- 팩토리 메서드 패턴과 흡사하지만, 사용하는 쪽 코드는 다르다.
2. 패턴 적용
- 팩토리 메서드 패턴
- 조건에 따른 객체 생성을 팩토리 클래스로 위임하여, 팩토리 클래스에서 객체를 생성하는 패턴
- 추상 팩토리 패턴
- 서로 관련이 있는 객체들을 통쨰로 묶어서 팩토리 클래스로 만들고, 이들 팩토리를 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성하는 패턴
즉, 추상 팩토리 패턴은 팩토리 메소드를 한번 더 추상 팩토리로 묶고 어떤 클래스를 구현할 것인지 클라이언트 코드에서 주입해 구체적인 클래스의 의존성을 최대한 제거한 구조
-> 어떤 클래스의 인스턴스를 사용할 것인지 가장 외부에서 호출하는 클라이언트에게 내부를 감출 수 있다.
-> 호출하는 쪽은 구현에 신경쓰지 않고 호출만 하면 된다 -> 느슨한 결합
// 1. 먼저 팩토리 패턴에 구현했던 Ship객체에 부품 anchor와 wheel 추가
@Setter
@Getter
@ToString
public class Ship {
private String name;
private String email;
private String logo;
//부품 (03 추상 팩토리)
private AnChore anchor;
private Wheel wheel;
public void setAnchor(AnChore anchor) {
this.anchor = anchor;
}
public void setWheel(Wheel wheel) {
this.wheel = wheel;
}
}
public interface AnChore {
}
public interface Wheel {
}
// 2. 그 다음 어떤 부품을 선택할것인지 구현의 선택을 담당하는 부품 팩토리 생성
public interface ShipPartsFactory {
AnChore createAnchor();
Wheel createWheel();
}
public class WhiteShipPartsFactory implements ShipPartsFactory{
@Override
public AnChore createAnchor() {
return new WhiteAnchor();
}
@Override
public Wheel createWheel() {
return new WhiteWheel();
}
}
// 3. 그 다음 배를 만드는 ShipFactory 를 interface 로 선언
public interface ShipFactory {
default Ship orderShip(String name, String email) {
validate(name, email);
return createShip();
}
Ship createShip();
private void validate(String name, String email) {
//validate
}
}
public class WhiteShipFactory implements ShipFactory {
private ShipPartsFactory shipPartsFactory;
public WhiteShipFactory(ShipPartsFactory shipPartsFactory) {
this.shipPartsFactory = shipPartsFactory;
}
@Override
public Ship createShip() {
Ship ship = new WhiteShip();
ship.setAnchor(shipPartsFactory.createAnchor());
ship.setWheel(shipPartsFactory.createWheel());
return ship;
}
}
// 4. 이렇게 한다면 클라이언트 쪽에서, 어떤 구현을 원하는지 주입해주기만 하면 되기 팩토리 패턴과 마찬가지로 요구사항이 변경되어도 내부 코드는 변경되지 않고 확장할 수 있는 구조가 된다.
public class ShipInventory {
public static void main(String[] args) {
ShipFactory whiteShipFactory = new WhiteShipFactory(new WhiteShipPartsFactory());
Ship ship = whiteShipFactory.createShip();
System.out.println("ship.getAnchor().getClass() = " + ship.getAnchor().getClass());
System.out.println("ship.getWheel().getClass() = " + ship.getWheel().getClass());
ShipFactory whiteProShipFactory = new WhiteShipFactory(new WhiteShipProPartsFactory());
}
}
3. 장점과 단점
- 디자인 패턴이 비슷비슷하게 생긴게 많음 -> 디자인패턴의 특징
- 이렇게 다른 이유는 관점이 다르기 때문
- 둘 다 구체적인 객체 생성 과정을 추상화한 인터페이스 제공
- 관점의 차이
- 팩토리 메서드 패턴의 경우엔 “객체 구현”에 초점을 둔다.
- 팩토리 메서드 패턴은 구체적인 객체 생성 과정을 하위 또는 구체적인 클래스로 옮기는 것이 목적
- 하위 클래스가 객체를 내맘대로 만들기 위한 패턴
- ex - createShip()을 서브클래스가 재정의
- 팩토리 메서드 패턴은 구체적인 객체 생성 과정을 하위 또는 구체적인 클래스로 옮기는 것이 목적
- 추상 팩토리 패턴의 경우엔 “사용 하는 부분”에 초점을 둔다.
- 추상 팩토리 패턴은 관련있는 여러 객체를 구체적인 클래스에 의존하지 않고 만들 수 있게 해주는 것이 목적
- 팩토리를 갈아껴서 만드는 패턴
- 즉, Product를 생상(Creator)하는 Factory를 인터페이스로 묶어두어 -> 클라이언트 쪽에서는 구체적인 클래스가 아닌 인터페이스에 의존하게 작성 가능
- ex - WhitePartsFactory, BlackPartsFactory를 바꿔끼는 구조
- 추상 팩토리 패턴은 관련있는 여러 객체를 구체적인 클래스에 의존하지 않고 만들 수 있게 해주는 것이 목적
- 팩토리 메서드 패턴의 경우엔 “객체 구현”에 초점을 둔다.
4. 자바와 스프링에서 찾아보는 패턴
- 자바 라이브러리
- javax.xml.xpath.XPathFactory#newInstance()
- javax.xml.transform.TransformerFactory#newInstance()
- javax.xml.parsers.DocumentBuilderFactory#newInstance()
- 스프링
- FactoryBean과 그 구현체