Ian's Archive 🏃🏻

Profile

Ian

Ian's Archive

Developer / React, SpringBoot ...

📍 Korea
Github Profile →
Categories
All PostsAlgorithm19Book1C1CI/CD2Cloud3DB1DesignPattern9ELK4Engineering1Front3Gatsby2Git2IDE1JAVA7JPA5Java1Linux8Nginx1PHP2Python1React9Security4SpatialData1Spring26
thumbnail

추상 팩토리 정리

DesignPattern
2025.10.20.

추상 팩토리 패턴

1. 패턴 소개

  • 관련 있는 여러 인스턴스를 만들어 주는 팩토리를 추상화된 형태로 정의하는 형태
  • 팩토리 메서드 패턴과 흡사하지만, 사용하는 쪽 코드는 다르다.

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());
    }
}

2

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과 그 구현체

Reference

코딩으로 학습하는 GoF의 디자인 패턴 - 백기선

Previous Post
팩토리 메서드 패턴 정리
Next Post
빌더 패턴 정리
Thank You for Visiting My Blog, I hope you have an amazing day 😆
© 2023 Ian, Powered By Gatsby.