헤드퍼스트 디자인패턴 3. 데코레이터 패턴스터디2024. 10. 22. 13:02
Table of Contents
요약
이 장에서 소개한 디자인 원칙
- OCP(Open-Closed Principle) 개방 폐쇄 원칙
- 모순이라고 여겨지지만, 코드를 변경하지 않아도 시스템을 확장하게 해주는 객체지향 기법이 존재
데코레이터 패턴
- 객체에 추가 요소를 동적으로 더할 수 있게 해주는 패턴
- 데코레이터를 사용해 서브 클래스를 만들 때보다 훨씬 유연하게 기능을 확장할 수 있음
문제 상황
아래와 같은 커피 전문점의 주문 시스템이 존재한다.
위 시스템에 메뉴를 추가하게 되면,, 아래와 같은 상황이 펼쳐진다.
주로 다음과 변경 사항이 발생했다.
- 첨가물 (우유, 휘핑 등) 의 추가
- 첨가물 가격 변동
- 베이스가 되는 메뉴 자체의 추가
- 메뉴 변동
이러한 문제를 데코레이터 패턴을 사용해 해결해보자.
데코레이터 패턴을 사용하면 위와 같이 구조를 설계할 수 있다.
인터페이스인 Beverage를 구현한 구체 메뉴 클래스들이 존재하고, 마찬가지로 Beverage를 구현한 CondimentDecorator 라는 추상 데코레이터와 이를 구현한 구체 데코레이터들이 존재한다.
데코레이터는 상속을 사용하지 않고, 구성을 통해 행위를 확장한다고 했는데 Decorator가 Beverage를 상속받는 이유는, 여기서의 '상속'은 단순히 행위의 형식을 맞추는 것 뿐이기 때문이다. 실제 행동은 데코레이터를 통해 정의하고 이를 구성하여 확장하게 된다.
실제 코드의 예제를 살펴보면 아래와 같다.
Beverage (추상 음료)
public abstract class Beverage {
String description = "제목 없음";
// 기본적으로 음료 자체에 대한 설명을 출력
public String getDescription() {
return description;
}
public abstract double cost();
}
CondimentDecorator (추상 데코레이터)
public abstract class CondimentDecorator extends Beverage {
Beverage beverage;
// 데코레이터에서 추가한 첨가물에 대한 설명을 출력하기 위해 description 게터를 추상 메서드로 설정
public abstract String getDescription();
}
Espresso (구체 음료)
public class Espresso extends Beverage {
public Espresso() {
description = "에스프레소";
}
public double cost() {
return 2.01;
}
}
HouseBlend (구체 데코레이터)
public class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
// 첨가물에 대한 설명을 추가
return beverage.getDescription() + ", 모카";
}
public double cost() {
// 첨가물에 대한 가격을 추가
return beverage.cost() + 0.20;
}
}
'스터디' 카테고리의 다른 글
헤드퍼스트 디자인패턴 2. 옵저버 패턴 (0) | 2024.10.09 |
---|---|
헤드퍼스트 디자인패턴 1. 전략 패턴 (3) | 2024.10.03 |
@gmelon :: gmelon's greenhouse
백엔드 개발을 공부하고 있습니다.