[객체 생성 패턴] Chapter 3-4. Abstract Factory Pattern : Java와 Spring에서 찾아보는 추상 팩토리 패턴

 

✍️ 추상 팩토리 패턴, Java에서 찾아보기

Java의 javax.xml.parsers.DocumentBuilderFactory에서 추상 팩토리 패턴을 찾아볼 수 있다.

Java는 xml형식의 문서를 객체화 시켜 살펴볼 수 있는 DocumentBuilder를 제공하는데 이는 DocumentBuilderFactory로부터 얻어올 수 있다. 

 

newInstance를 통해 얻어오는 DocumentBuilderFactory 타입의 객체가 ConcreteFactory에 해당하고 ConcreteFactory가 제공하는 DocumentBuilder가 추상화된 객체(제품)에 해당한다.

public class DocumentBuilderFactoryExample {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse("src/main/resources/config.xml");
        System.out.println(document.getDocumentElement());
    }
}
public abstract class DocumentBuilder {
}

 

 

🍊추상 팩토리 패턴, Spring에서 찾아보기

스프링에선 FactoryBean에서 추상 팩토리 패턴을 찾아볼 수 있다.

 

FactoryBean은 스프링이 제공하는 인터페이스로, (XML 설정 기준) 기본으로 제공되는 스프링 구문으로는 생성 및 관리할 수 없는 객체를 Bean으로 활용할 수 있게끔 어댑터 역할을 한다. 여기서 생성 및 관리할 수 없는 객체란 생성자가 private한 싱글톤 객체 혹은 정적 팩토리 메서드를 통해 얻어오는 객체가 이에 해당한다.

 

 

가장 직관적인 예시로 싱글톤을 생각해 보자. 이제 Ship 클래스는 싱글톤 객체만을 제공한다. 만약 싱글톤 객체를 Bean으로 활용하고 싶다면 FactoryBean을 고려해 볼 수 있다.

package _03_AbstractFactory._03_java;

public class Ship {
    private static final Ship INSTANCE = new Ship();
    // 편의상 public
    private String name = "Singleton_TurtleShip";
    private String color = "Green";
    private String logo = "\uD83D\uDC22";

    private Ship(){
    }

    @Override
    public String toString() {
        return "Ship{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", logo='" + logo + '\'' +
                '}';
    }

    public static Ship getInstance() {
        return INSTANCE;
    }
}

 

FactoryBean의 구현체를 만들고 구현체를 Bean으로 등록하면, ShipFactory의 getObject에서 반환하는 객체가 최종적으로 Bean으로 등록된다.

public class ShipFactory implements FactoryBean<Ship> {
    @Override
    public Ship getObject() throws Exception {
        return Ship.getInstance();
    }

    @Override
    public Class<?> getObjectType() {
        return Ship.class;
    }
}

 

중간 정리를 해보면,

FactoryBean은 추상 팩토리 인터페이스에 해당하고

ShipFactory는 구현체인 ConcreteFactory에 해당한다.

스프링은 ShipFactory를 사용하는 클라이언트에 해당한다.

 

실제 테스트를 해보면 우리는 Bean에 myShip이란 아이디로 ShipFactory를 등록했는데, ApplicationContext로부터 가져올 땐 ShipFactory가 제공하는 싱글톤 객체를 얻어온다. 

<bean id="myShip" class="_03_AbstractFactory._03_java.ShipFactory"/>
public class FactoryBeanExample {
    public static void main(String[] args) throws Exception {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml");
        Ship myShip = applicationContext.getBean("myShip", Ship.class);
        System.out.println(myShip);
    }
}
실행결과

Ship{name='Singleton_TurtleShip', color='Green', logo='🐢'}

 

인프런의 백기선님의 강의 코딩으로 학습하는 GoF의 디자인 패턴을 참고해서 작성했습니다.

 

코딩으로 학습하는 GoF의 디자인 패턴 - 인프런 | 강의

디자인 패턴을 알고 있다면 스프링 뿐 아니라 여러 다양한 기술 및 프로그래밍 언어도 보다 쉽게 학습할 수 있습니다. 또한, 보다 유연하고 재사용성이 뛰어난 객체 지향 소프트웨어를 개발할

www.inflearn.com