Posted:      Updated:

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

템플릿 메서드 패턴(Template Method Pattern)

  • 전체적으로는 동일하면서 부분적으로는 다른 구문으로 구성된 메서드의 코드 중복 최소화
  • 동일한 기능은 상위 클래스에서 정의
  • 확장, 변화가 필요한 부분만 서브 클래스에서 구현
  • 알고리즘 코드 재사용에 유용함

템플릿 메서드 패턴 컬레보레이션

  • AbstractClass
    • 템플릿 메서드 정의 클래스
    • 하위 클래스에 공통 알고리즘 정의
    • 하위 클래스에 구현될 기능을 primitive 메서드 혹은 hook 메서드로 정의
  • ConcreteClass
    • primitive 메서드, hook 메서드 구현
    • 상위 클래스의 일반적인 알고리즘에서 하위 클래스에 적합하게 오버라이드

예시: 여러 회사의 모터 지원

  • 엘레베이터 제어 시스템에서 모터를 구동시키는 기능
  • HyundaiMotor, LGMotor 2가지의 모터를 사용할 수 있음
  • 각 모터의 구동 방식은 완전히 동일하지는 않으나 많은 중복 코드를 가짐
  • Motor : AbstractClass
    • move 메서드 : 템플릿 메서드
    • moveMotor 메서드 : primitive 메서드, 추상 메서드, 하위 클래스에서 오버라이드
  • HyundaiMotor, LGMotor : ConcreteClass
  • 상위 Motor 클래스의 move 메서드에서 다른 부분은 moveMotor 메서드 호출을 이용

전체 코드

public enum DoorStatus { CLOSED, OPENED }
public enum Direction { UP, DOWN }
public enum MotorStatus { MOVING, STOPPED }

public class Door {
    private DoorStatus doorStatus;

    public Door() {
        doorStatus = DoorStatus.CLOSED;
    }

    public DoorStatus getDoorStatus() {
        return doorStatus;
    }

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

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

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

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

    public MotorStatus getMotorStatus() {
        return motorStatus;
    }

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

    public void move(Direction direction) {
        MotorStatus motorStatus = getMotorStatus();
        if (motorStatus == MotorStatus.MOVING) {
            System.out.println("모터가 움직이고 있습니다.");
            return;
        }

        DoorStatus doorStatus = door.getDoorStatus();
        if (doorStatus == DoorStatus.OPENED) {
            System.out.println("문을 닫습니다.");
            door.close();
        }

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

    protected abstract void moveMotor(Direction direction);
}

public class HyundaiMotor extends Motor {
    public HyundaiMotor(Door door) {
        super(door);
    }

    @Override
    protected void moveMotor(Direction direction) {
        System.out.println("HyundaiMotor 구동");
        System.out.println("방향: "+direction);
    }
}

public class LGMotor extends Motor {
    public LGMotor(Door door) {
        super(door);
    }

    @Override
    protected void moveMotor(Direction direction) {
        System.out.println("LGMotor 구동");
        System.out.println("방향: "+direction);
    }
}

public class Main {
    public static void main(String[] args) {
        Door door = new Door();
        HyundaiMotor hyundaiMotor = new HyundaiMotor(door);
        hyundaiMotor.move(Direction.UP);

        door.open();
        LGMotor lgMotor = new LGMotor(door);
        lgMotor.move(Direction.DOWN);
    }
}

출력

HyundaiMotor 구동
방향: UP
문을 닫습니다.
LGMotor 구동
방향: DOWN

댓글남기기