데코레이터 패턴은 객체의 구조를 변경하지 않고 기능을 동적으로 확장할 수 있는 디자인 패턴 중 하나이다.
이 패턴은 객체에 새로운 기능을 추가하거나 변경할 때, 서브 클래스를 생성하지 않고도 구현할 수 있도록 한다.
데코레이터 패턴의 주요 구성 요소
- Component(구성 요소):
- 기본 기능을 정의하는 인터페이스 또는 추상 클래스이다.
- ConcreteComponent(구체적인 구성 요소):
- Component의 구현 클래스로, 실제로 기본 기능을 구현한다.
- Decorator(데코레이터):
- Component를 상속하며, Component의 하위 클래스들을 데코레이팅하는 역할을 한다. 데코레이터는 동일한 인터페이스를 갖고 있어야 한다.
- ConcreteDecorator(구체적인 데코레이터):
- Decorator의 구현 클래스로, 실제로 기능을 추가하거나 변경하는 역할을 한다.
주의 사항
데코레이터 패턴을 쓰면 관리해야 할 객체가 늘어난다. 때문에 실제로는 팩토리나 빌더 같은 다른 패턴으로 데코레이터를 만들어 사용한다.
데코레이터 내부의 요소(구체적인 구성 요소)로 돌아가는 코드를 만들어야 한다면 데코레이터 패턴 사용을 다시 한번 생각해 봐야 한다.
예제
// 컴포넌트 인터페이스
interface Beverage {
double cost(); // 가격을 반환하는 메서드
String getDescription(); // 설명을 반환하는 메서드
}
// 구체적인 컴포넌트
class Espresso implements Beverage {
@Override
public double cost() {
return 1.99;
}
@Override
public String getDescription() {
return "에스프레소";
}
}
// 데코레이터 팩토리 인터페이스
interface CondimentFactory {
Beverage addCondiment(Beverage beverage);
}
// 구체적인 데코레이터 팩토리
class MilkFactory implements CondimentFactory {
@Override
public Beverage addCondiment(Beverage beverage) {
return new Milk(beverage);
}
}
class MochaFactory implements CondimentFactory {
@Override
public Beverage addCondiment(Beverage beverage) {
return new Mocha(beverage);
}
}
// 데코레이터
abstract class CondimentDecorator implements Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
// 구체적인 데코레이터
class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return beverage.cost() + 0.5;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 우유";
}
}
class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return beverage.cost() + 0.75;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 모카";
}
}
public class Main {
public static void main(String[] args) {
// 팩토리를 이용하여 데코레이터 생성
CondimentFactory milkFactory = new MilkFactory();
CondimentFactory mochaFactory = new MochaFactory();
// 주문: 에스프레소에 우유와 모카 추가
Beverage beverage = new Espresso();
beverage = milkFactory.addCondiment(beverage);
beverage = mochaFactory.addCondiment(beverage);
System.out.println("주문: " + beverage.getDescription());
System.out.println("가격: $" + beverage.cost());
}
}
728x90
'디자인 패턴' 카테고리의 다른 글
Factory Pattern (0) | 2024.05.18 |
---|---|
Facade Pattern (0) | 2024.05.12 |
Composite Pattern (1) | 2024.05.01 |
Command Pattern (0) | 2024.04.28 |
Chain Of Responsibility Pattern (0) | 2024.04.27 |