Java/디자인 패턴

[디자인 패턴] 추상 팩토리

태감새 2023. 3. 2. 22:11

코딩으로 학습하는 GoF의 디자인 패턴

추상 팩토리

서로 관려있는 여러 객체를 만들어주는 인터페이스. 클라이언트 코드에서 구체적인 클래스의 의존성을 제거한다.

예제

Part

public interface Anchor { }
public interface Wheel { }
public interface ShipPartsFactory {  
    Anchor createAnchor();  

    Wheel createWheel();  
}

WhiteShip

public class WhiteShipFactory extends DefaultShipFactory {  

    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;  
    }  
}
public class WhiteShipPartsFactory implements ShipPartsFactory {  
    @Override  
    public Anchor createAnchor() {  
        return new WhiteAnchor();  
    }  

    @Override  
    public Wheel createWheel() {  
        return new WhiteWheel();  
    }  
}
public class WhiteAnchor implements Anchor { }
public class WhiteWheel implements Wheel { }

WhiteShipPro

public class WhiteShipPartsProFactory implements ShipPartsFactory {  
    @Override  
    public Anchor createAnchor() {  
        return new WhiteAnchorPro();  
    }  

    @Override  
    public Wheel createWheel() {  
        return new WhiteWheelPro();  
    }  
}
public class WhiteAnchorPro implements Anchor { }
public class WhiteWheelPro implements Wheel { }

Client

public class ShipInventory {  
    public static void main(String[] args) {  
        ShipFactory shipFactory = new WhiteShipFactory(new WhiteShipPartsFactory());  
        Ship ship = shipFactory.createShip();  
        System.out.println(ship.getAnchor().getClass());  
        System.out.println(ship.getWheel().getClass());  

        ShipFactory shipFactoryPro = new WhiteShipFactory(new WhiteShipPartsProFactory());  
        Ship shipPro = shipFactoryPro.createShip();  
        System.out.println(shipPro.getAnchor().getClass());  
        System.out.println(shipPro.getWheel().getClass());  
    }  
}

ShipPartFactory에는 Wheel과 Anchor를 참조하는 메서드를 정의했다. White와 WhitePro는 이 세가지를 구현해서 각자 맞는 구현체를 작성한다. 그리고 다형성을 이용하여 WhiteShipFactory에서 ShipPartFactory구현체를 입력받아 ship을 반환한다.

 

팩토리 메서드와 추상 팩토리의 차이점

공통점

둘 다 구체적인 객체 생성 과정을 추상화한 인터페이스를 제공한다.

차이점

  1. 관점
    1. 팩토리 메서드 : 팩토리를 구현하는 방법에 초점
    2. 추상 팩토리 : 팩토리를 사용하는 방법에 초점
  1. 목적
    1. 팩토리 메서드 : 구체적인 객체 생성 과정을 하위로 옮기는 것이 목적
    2. 추상 팩토리 : 관련있는 여러 객체를 구체적인 클래스에 의존하지 않고 만들 수 있게 해주는 것이 목적

 

팩토리 메서드는 shipFactory.orderShip하면 배의 주문 과정이 실행된다. 클라이언트는 orderShip메서드의 내용을 몰라도 원하는 배의 Factory를 지정하여 orderShip하면 원하는 결과가 도출된다.

추상 팩토리의 ShipPartFactory는 Wheel과 Anchor를 생성하는 메서드를 가지고 shipFactory는 ShipPartFactory의 구현체를 주입받아 ship을 생성한다.

 

개인적인 견해

둘 다 객체 생성의 과정을 추상화한 패턴이고 관점과 목적이 다르다고 한다. 그렇다면 사용방법은 같다는 말이 아닐까. 백기선님이 강의 중에 물컵을 들고 시선을 옮기면서 관점의 차이를 설명했는데 결국 컵이라는 실체는 하난데 보는 관점이 다른거니까 두 패턴의 차이점을 찾는 것이 어려운게 당연하다. 구체적인 과정을 추상화해서 숨기는게 목적이면 팩토리 메서드 패턴, 여러 객체가 있을 때 이들을 추상의 팩토리로 엮어주는 것이 팩토리 메서드 패턴이라고 이해했다. 뭔가 팩토리 메서드 패턴에서 확장되면 추상 팩토리 패턴이 될거같은 느낌이 든다.