해당 포스팅은 한빛 미디어 헤드퍼스트 디자인 패턴(에릭 프리먼, 엘리자베스 롭슨 저)를 통해 공부한 내용을 정리한 블로그입니다.

아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
좋은 프로그래머는 자기 두뇌를 사용한다. 그러나 좋은 가이드라인은 모든 케이스를 고려해야만 하는 노력을 줄여준다.
(Francis Glassborow, 개발자)

카페 프로그램 개발


  • 음료수가 많으니 추상 클래스에서 Beverage 클래스 정의
  • 더 자세한 음료는 서브 클래스에서 구현

문제점

  • 인기가 증가하면서 메뉴가 너무 많이 증가하고, 모든 메뉴가 Beverage를 상속함
  • 첨가물도 있으니 첨가물이나 가격변동에 따른 대비가 어려움

해결책

  • 인스턴스 변수와 슈퍼 클래스 상속으로 관리

문제점

  1. 첨가물의 가격이 바뀔때마다 코드 수정
  2. 새로운 음료가 출시될 경우, 특정 첨가물이 들어가면 안되는 음료가 있을 수 있음.
  3. 같은 첨가물을 두번 주문하는 경우

고찰


  • 상속만으로는 무조건 유연하거나 관리하기 좋은 디자인은 아님
  • 구성과 위임으로 실행 중에 행동을 상속하는 방법이 있음
    • 서브 클래스로 행동을 상속받으면 컴파일 타임에 결정됨.
    • 구성으로 객체의 행동을 확장하면 실행 중에 동적으로 할당가능.
💡 OCP(Open-Closed Principle)
클래스 확장에는 열려있지만 변경에는 닫혀있다.

 

Decorator Pattern


이전까지는 클래스가 너무 많아지거나 적합하지 않은 기능을 추가해야했음.

첨가물 == 음료의 장식(decorate)으로 생각

Decorator Pattern

방법

  1. DarkRoast 객체 생성
  2. Mocha 객체로 장식
  3. Whip 객체로 장식
  4. cost() 메서드 호출. 첨가물의 가격을 계산하는 일은 객체에게 위임.

정리

  1. 데코레이터의 슈퍼 클래스는 자신이 장식하고 있는 객체의 슈퍼클래스와 동일(Beverage)
  2. 한 객체(음료)를 여러개의 데코레이터(샷, 우유, 모카...)로 감싸기
  3. 데코레이터는 행동을 위임하는것 말고도 다른 추가 메서드 가능
  4. 실행중에 데코레이터 적용 가능
💡 Decorator Pattern
객체에 추가 요소를 동적으로 더할 수 있음.
서브 클래스를 만들때보다 유연하게 기능확장 가능.

 

고찰

  • CondimentDecorator에서 Beverage 클래스를 확장 ⇒ 상속아닌가?
    • 상속맞지만 행동을 물려받는게 아님
  • 이 구조로 실행 중에 동적으로 결정 가능

Java IO 클래스

데코레이터 패턴을 적용한 예

예시

public abstract class Beverage {
    enum SIZE {
        TALL, GRANDE, VENTI
    }

    String description = "아무것도 없음";
    SIZE size = SIZE.TALL;

    public String getDescription() {
        return description;
    }

    public SIZE getSize() {
        return size;
    }

    public void setSize(SIZE size) {
        this.size = size;
    }

    abstract double cost();
}

public abstract class CondimentDecorator extends Beverage {
    Beverage beverage;

    public abstract String getDescription();
}


public class DarkRoast extends Beverage {
    private double cost;

    public DarkRoast() {
        description = "다크 로스트 커피";
    }

    double cost() {
        if (getSize() == SIZE.TALL) {
            cost += 0.99;
        } else if (getSize() == SIZE.GRANDE) {
            cost += 1.49;
        } else {
            cost += 1.99;
        }

        return cost;
    }
}

public class Mocha extends CondimentDecorator {
    public Mocha(Beverage b) {
        this.beverage = b;
    }

    public String getDescription() {
        return beverage.getDescription() + "모카";
    }

    public double cost() {
        return beverage.cost() + 0.2;
    }
}

public class Whip extends CondimentDecorator {
    public Whip(Beverage b) {
        description = "휘핑";
        this.beverage = b;
    }

    public String getDescription() {
        return beverage.getDescription() + "휘핑";
    }

    public double cost() {
        return beverage.cost() + 0.4;
    }
}

public class StarbuzzCoffee {
    public static void main(String[] args) {
        Beverage espresso = new Espresso();
        System.out.println("espresso: " + espresso.getDescription() + " cost: " + espresso.cost());

        Beverage darkRoast = new DarkRoast();
        darkRoast = new Mocha(darkRoast);
        darkRoast = new Mocha(darkRoast);
        darkRoast = new Whip(darkRoast);
        System.out.println("Dark double Mocha whipping: " + darkRoast.getDescription() + " cost: " + darkRoast.cost());

        Beverage sameB = new Whip(new Mocha(new Mocha(new DarkRoast())));
        System.out.println("Dark double Mocha whipping: " + sameB.getDescription() + " cost: " + sameB.cost() + "\t" + sameB.getClass());

        // SIZE = GRANDE;
        Beverage darkRoastGrande = new DarkRoast();
        darkRoastGrande.setSize(Beverage.SIZE.GRANDE);
        darkRoastGrande = new Mocha(darkRoastGrande);
        darkRoastGrande = new Mocha(darkRoastGrande);
        darkRoastGrande = new Whip(darkRoastGrande);
        System.out.println("Dark Grande double Mocha whipping: " + darkRoastGrande.getDescription() + " cost: " + darkRoastGrande.cost());
    }
}

'기타 > 디자인패턴' 카테고리의 다른 글

[Design Pattern] Command Pattern  (2) 2024.06.03
[Design Pattern] Singleton Pattern  (0) 2024.05.31
[Design Pattern] Factory Pattern  (0) 2024.05.29
[Design Pattern] Observer Pattern  (0) 2024.05.27
[Design Pattern] Strategy Pattern  (0) 2024.05.27

+ Recent posts