Posted:      Updated:

자바 디자인 패턴 스터디를 하며 ‘Java 객체 지향 디자인 패턴’ 교재를 정리한 글입니다.

추상 팩토리 패턴(Abstract Factory Pattern)

  • 관련성 있는 여러 종류의 객체를 일관된 방식으로 생성
  • 서로 연관되거나 의존적인 객체들의 조합을 만듦

추상 팩토리 패턴 컬레보레이션

  • AbstractFactory
    • 실제 팩토리 클래스의 공통 인터페이스
    • 각 제품의 부품을 생성하는 기능을 추상 메서드로 정의
  • ConcreteFactory
    • 구체적인 팩토리 클래스
    • AbstractFactory 클래스의 추상 메서드를 오버라이드
    • 구체적인 제품 생성
  • AbstractProduct
    • 제품의 공통 인터페이스
  • ConcreteProduct
    • 구체적인 팩토리 클래스에서 생성되는 구체적인 제품

예시: 엘리베이터 부품 업체 변경하기

  • 엘리베이터마다 다른 제조 업체의 부품을 사용할 때 프로그램 변경 최소화

전체 코드

public enum Direction {
    UP, DOWN
}

public enum DoorStatus {
    OPENED, CLOSED
}

public enum MotorStatus {
    MOVING, STOPPED
}

public enum VendorID {
    LG, HYUNDAI
}

public abstract class DirectionLamp {
    private Direction lampStatus;

    public void light(Direction direction) {
        if (lampStatus == getLampStatus()) {
            return;
        }
        doLight(lampStatus);
        setLampStatus(lampStatus);
    }

    private Direction getLampStatus() {
        return lampStatus;
    }

    private void setLampStatus(Direction lampStatus) {
        this.lampStatus = lampStatus;
    }

    protected abstract void doLight(Direction lampStatus);
}

public abstract class Door {
    private DoorStatus doorStatus;

    public Door() {
        this.doorStatus = DoorStatus.OPENED;
    }

    public DoorStatus getDoorStatus() {
        return doorStatus;
    }

    public void close() {
        if (doorStatus == DoorStatus.CLOSED) {
            return;
        }
        doClose();
        doorStatus = DoorStatus.CLOSED;
    }

    protected abstract void doClose();

    public void open() {
        if (doorStatus == DoorStatus.OPENED) {
            return;
        }
        doOpen();
        doorStatus = DoorStatus.OPENED;
    }

    protected abstract void doOpen();
}

public class DoorFactory {
    public static Door createDoor(VendorID vendorID) {
        Door door = null;

        switch (vendorID) {
            case LG: door = new LgDoor(); break;
            case HYUNDAI: door = new HyundaiDoor(); break;
        }

        return door;
    }
}

public class Elevator {
    private Motor motor;
    private Door door;
    private DirectionLamp lamp;

    public void setLamp(DirectionLamp lamp) {
        this.lamp = lamp;
    }

    public void setMotor(Motor motor) {
        this.motor = motor;
    }

    public void setDoor(Door door) {
        this.door = door;
    }

    public void move(Direction direction) {
        motor.move(direction);
        lamp.doLight(direction);
    }
}

public class ElevatorCreator {
    public static Elevator assembleElevator(ElevatorFactory factory) {
        Elevator elevator = factory.createElevator();

        Motor motor = factory.createMotor();
        elevator.setMotor(motor);

        Door door = factory.createDoor();
        elevator.setDoor(door);
        motor.setDoor(door);

        DirectionLamp lamp = factory.createLamp();
        elevator.setLamp(lamp);

        return elevator;
    }
}

public abstract class ElevatorFactory {
    public abstract Elevator createElevator();
    public abstract Motor createMotor();
    public abstract Door createDoor();
    public abstract DirectionLamp createLamp();
}

public class HyundaiElevator extends Elevator {
}

public class HyundaiDoor extends Door{
    @Override
    protected void doClose() {
        System.out.println("Close Hyundai Door");
    }

    @Override
    protected void doOpen() {
        System.out.println("Open Hyundai Door");
    }
}

public class HyundaiElevatorFactory extends ElevatorFactory{
    @Override
    public Elevator createElevator() {
        return new HyundaiElevator();
    }

    @Override
    public Motor createMotor() {
        return new HyundaiMotor();
    }

    @Override
    public Door createDoor() {
        return new HyundaiDoor();
    }

    @Override
    public DirectionLamp createLamp() {
        return new HyundaiLamp();
    }
}

public class HyundaiLamp extends DirectionLamp{
    @Override
    protected void doLight(Direction direction) {
        System.out.println("Hyundai Lamp "+direction);
    }
}

public class HyundaiMotor extends Motor{
    @Override
    protected void moveMotor(Direction direction) {
        System.out.println("Hyundai motor is Moving "+direction);
    }
}

public class LampFactory {
    public static DirectionLamp createLamp(VendorID vendorID) {
        DirectionLamp lamp = null;

        switch (vendorID) {
            case LG: lamp = new LgLamp(); break;
            case HYUNDAI: lamp = new HyundaiLamp(); break;
        }

        return lamp;
    }
}

public class LgDoor extends Door{
    @Override
    protected void doClose() {
        System.out.println("Close Lg Door");
    }

    @Override
    protected void doOpen() {
        System.out.println("Open Lg Door");
    }
}

public class LgElevator extends Elevator {
}

public class LgElevatorFactory extends ElevatorFactory{
    @Override
    public Elevator createElevator() {
        return new LgElevator();
    }

    @Override
    public Motor createMotor() {
        return new LgMotor();
    }

    @Override
    public Door createDoor() {
        return new LgDoor();
    }

    @Override
    public DirectionLamp createLamp() {
        return new LgLamp();
    }
}

public class LgLamp extends DirectionLamp{
    @Override
    protected void doLight(Direction direction) {
        System.out.println("Lg Lamp "+direction);
    }
}

public class LgMotor extends Motor{
    @Override
    protected void moveMotor(Direction direction) {
        System.out.println("Lg motor is Moving "+direction);
    }
}

public abstract class Motor {
    private Door door;
    private MotorStatus motorStatus;

    public void setDoor(Door door) {
        this.door = door;
        this.motorStatus = MotorStatus.STOPPED;
    }

    public void move(Direction direction) {
        MotorStatus motorStatus = getMotorStatus();
        if (motorStatus == MotorStatus.MOVING) {
            return;
        }

        DoorStatus doorStatus = door.getDoorStatus();
        if (doorStatus == DoorStatus.OPENED) {
            door.close();
        }

        moveMotor(direction);
        setMotorStatus(MotorStatus.MOVING);
    }

    private void setMotorStatus(MotorStatus motorStatus) {
        this.motorStatus = motorStatus;
    }

    protected abstract void moveMotor(Direction direction);

    private MotorStatus getMotorStatus() {
        return motorStatus;
    }
}

public class MotorFactory {
    public static Motor createMotor(VendorID vendorID) {
        Motor motor = null;

        switch (vendorID) {
            case LG: motor = new LgMotor(); break;
            case HYUNDAI: motor = new HyundaiMotor(); break;
        }

        return motor;
    }
}

public class Main {
    public static void main(String[] args) {
        ElevatorFactory factory = null;
        String vendorName = "LG";
        if (vendorName.equalsIgnoreCase("LG")) {
            factory = new LgElevatorFactory();
        }
        else {
            factory = new HyundaiElevatorFactory();
        }
        Elevator elevator = ElevatorCreator.assembleElevator(factory);
        elevator.move(Direction.UP);
    }
}

출력

Close Lg Door
Lg motor is Moving UP
Lg Lamp UP

댓글남기기