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
해당 주소로 이전하였습니다. 감사합니다. https://ililil9482.tistory.com

0개의 댓글