Abstract Factory Pattern

최준호·2022년 11월 15일
0

Design Pattern

목록 보기
4/7
post-thumbnail

📗 Abstract Factory Pattern

이전에 학습했던 Factory Method Pattern이 객체의 생성 책임을 추상 클래스 or 인터페이스(=Factory)에 맡겼던 패턴이라면 Abstract Factory Pattern은 객체의 생성 책임을 사용하는 입장에 맡긴 패턴이라고 생각하면 될거 같다.

말로 해서는 이해가 어렵다! 직접 패턴 코드를 보고 다시 이해해보자!

⌨️ 아이폰 만들기

📄 추상 정의하기

public interface IPhonePartsFactory {
    Chip createChip();
    Camera createCamera();
}
public interface Chip {
    String name();
}
public interface Camera {
    String name();
}

다음과 같이 기본 뼈대가 될 IPhonePartsFactory Chip Camera 를 먼저 정의해준다. 아이폰을 만들기 위해 Chip과 Camera를 파츠로 넣어야하고 각각의 파츠를 구현해서 넣어줄 것이다.

그리고 아이폰은 Plus Pro ProMax 버전만 있다고 가정하고 진행해보려고 한다!

📄 파츠 구현체 정의하기

chip과 camera를 구현해보자

public class PlusCamera implements Camera{
    @Override
    public String name() {
        return "Plus Camera";
    }
}
public class PlusChip implements Chip{
    @Override
    public String name() {
        return "Plus Chip";
    }
}

plus 라인의 부품들을 모두 만들어냈다.

📄 아이폰 제조 구현체 정의하기

이제 아이폰 제조 구현체를 정의해보자.

public class IPhonePlusFactory implements IPhonePartsFactory{
    @Override
    public Chip createChip() {
        return new PlusChip();
    }

    @Override
    public Camera createCamera() {
        return new PlusCamera();
    }
}

plus 제조 구현체까 모두 정의를 완료했다!

이제 우리는 아이폰 Plus 주문만 넣어주면 된다!

📄 아이폰 제조하기!

public class IPhone {
    private Camera camera;
    private Chip chip;

    public Camera getCamera() {
        return camera;
    }

    public void setCamera(Camera camera) {
        this.camera = camera;
    }

    public Chip getChip() {
        return chip;
    }

    public void setChip(Chip chip) {
        this.chip = chip;
    }
}

먼저 아이폰을 제조해야하니 아이폰 자체를 만들어주었다.

public class IPhoneOrderFactory {
    private IPhonePartsFactory iPhonePartsFactory;

    public IPhoneOrderFactory(IPhonePartsFactory iPhonePartsFactory) {
        this.iPhonePartsFactory = iPhonePartsFactory;
    }

    public IPhone createIPone(){
        IPhone iPhone = new IPhone();
        iPhone.setCamera(iPhonePartsFactory.createCamera());
        iPhone.setChip(iPhonePartsFactory.createChip());
        return iPhone;
    }
}

핵심 여기 부분이 핵심인데 주문이 들어오는 구현체가 어떤 구현체인지 따라 반환해주는 아이폰의 버전이 변경될 부분이다.

public class Client {
    public static void main(String[] args) {
        IPhoneOrderFactory iPhoneOrderFactory = new IPhoneOrderFactory(new IPhonePlusFactory());
        IPhone iPhone = iPhoneOrderFactory.createIPone();

        System.out.println(iPhone.getCamera().getClass());
        System.out.println(iPhone.getChip().getClass());
    }
}

주문을 해보면

다음과 같이 아이폰이 잘 제조된 것을 확인해볼 수 있다.

⌨️ 모델 라인 추가하기!

📄 파츠 구현체 정의하기 2

public class ProCamera implements Camera{
    @Override
    public String name() {
        return "Pro Camera";
    }
}
public class ProChip implements Chip{
    @Override
    public String name() {
        return "Pro Chip";
    }
}
public class ProMaxCamera implements Camera{
    @Override
    public String name() {
        return "Pro Max Camera";
    }
}
public class ProMaxChip implements Chip{
    @Override
    public String name() {
        return "Pro Max Chip";
    }
}

plus, pro, pro max 라인의 부품들을 모두 만들어냈다.

📄 아이폰 제조 구현체 정의하기 2

public class IPhoneProFactory implements IPhonePartsFactory{
    @Override
    public Chip createChip() {
        return new ProChip();
    }

    @Override
    public Camera createCamera() {
        return new ProCamera();
    }
}
public class IPhoneProMaxFactory implements IPhonePartsFactory{
    @Override
    public Chip createChip() {
        return new ProMaxChip();
    }

    @Override
    public Camera createCamera() {
        return new ProMaxCamera();
    }
}

plus, pro, pro max 제조 구현체까 모두 정의를 완료했다!

이제 우리는 고객이 원하는 아이폰 종류에 따라 주문만 넣어주면 된다!

📄 아이폰 제조하기! 2

public class Client {
    public static void main(String[] args) {
        IPhoneOrderFactory iPhoneOrderFactory1 = new IPhoneOrderFactory(new IPhonePlusFactory());
        IPhoneOrderFactory iPhoneOrderFactory2 = new IPhoneOrderFactory(new IPhoneProFactory());
        IPhoneOrderFactory iPhoneOrderFactory3 = new IPhoneOrderFactory(new IPhoneProMaxFactory());

        IPhone iPhone1 = iPhoneOrderFactory1.createIPone();
        IPhone iPhone2 = iPhoneOrderFactory2.createIPone();
        IPhone iPhone3 = iPhoneOrderFactory3.createIPone();

        System.out.println(iPhone1.getCamera().getClass());
        System.out.println(iPhone1.getChip().getClass());

        System.out.println(iPhone2.getCamera().getClass());
        System.out.println(iPhone2.getChip().getClass());

        System.out.println(iPhone3.getCamera().getClass());
        System.out.println(iPhone3.getChip().getClass());
    }
}

결과를 확인해보면 알맞은 부품들이 사용된 것을 확인할 수 있고

public class Client {
    public static void main(String[] args) {
        IPhoneOrderFactory iPhoneOrderFactory1 = new IPhoneOrderFactory(new IPhonePlusFactory());
        IPhoneOrderFactory iPhoneOrderFactory2 = new IPhoneOrderFactory(new IPhoneProFactory());
        IPhoneOrderFactory iPhoneOrderFactory3 = new IPhoneOrderFactory(new IPhoneProMaxFactory());

        IPhone iPhone1 = iPhoneOrderFactory1.createIPone();
        IPhone iPhone2 = iPhoneOrderFactory2.createIPone();
        IPhone iPhone3 = iPhoneOrderFactory3.createIPone();

        System.out.println(iPhone1.getCamera().name());
        System.out.println(iPhone1.getChip().name());

        System.out.println(iPhone2.getCamera().name());
        System.out.println(iPhone2.getChip().name());

        System.out.println(iPhone3.getCamera().name());
        System.out.println(iPhone3.getChip().name());
    }
}

우리가 구현한 기능으로 확인해 보면

동일하게 잘 나오는 것을 확인할 수 있다.

여기서 우리는 디자인 패턴의 힘을 느낄 수 있는데. 우리가 아이폰 생산 라인을 늘리면서 확장을 했지만 실제 IPone 관련 코드가 수정된 곳은 없다라는 점이다.(=OCP) 또한 생성자에 넣어주는 구현체마다 자신의 책임만을 갖고 있기 때문에 SRP를 지켰다고도 볼수 있다.(개인의 생각에 따라 의견이 다를 수 있음!)

📗 정리

📄 Factory Method Pattern과 차이점

앞서 말했던 Factory Method Pattern과의 차이점을 다시 짚어보려고 한다. 우선 Factory Method Pattern의 코드를 잠깐만 보면

public class Client {
    public static void main(String[] args) {
        Car car1 = new AvanteFactoryV2().orderCar("최준호", "white");
        Car car2 = new GV80FactoryV2().orderCar("최준호", "white");
    }
}

다음과 같이 구체적인 Factory를 가지고 객체를 생성해온다.

그에 반해

public class Client {
    public static void main(String[] args) {
        IPhoneOrderFactory iPhoneOrderFactory1 = new IPhoneOrderFactory(new IPhonePlusFactory());
        IPhoneOrderFactory iPhoneOrderFactory2 = new IPhoneOrderFactory(new IPhoneProFactory());
        IPhoneOrderFactory iPhoneOrderFactory3 = new IPhoneOrderFactory(new IPhoneProMaxFactory());

        IPhone iPhone1 = iPhoneOrderFactory1.createIPone();
        IPhone iPhone2 = iPhoneOrderFactory2.createIPone();
        IPhone iPhone3 = iPhoneOrderFactory3.createIPone();
    }
}

Abstract Factory Pattern의 경우 사용하려고 하는 입장에서 내가 어떤 부품으로 조립하고 싶은지 구현체를 짚어 넣어줘야 한다는 차이점이 있다.

이 둘은 거의 비슷해 보이지만
구체적인 구현체로 직접 객체를 반환해주느냐
혹은
주입된 구현체에 따라 객체를 반환해주느냐
차이점이라고 이해하면 될거 같다!

profile
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글