데코레이터 패턴(Decorator Pattern)은 구조적 디자인 패턴으로, 기존 객체의 기능을 확장하거나 수정할 때, 상속 대신 객체를 감싸는 방식으로 새로운 동작을 추가한다.
이를 통해 기존 코드 변경 없이 기능을 동적으로 추가할 수 있다.
소프트웨어 개발에서 클래스의 동작을 확장하려면 보통 상속을 사용하지만, 다음과 같은 문제점이 발생할 수 있다:
데코레이터 패턴은 이러한 문제를 해결하기 위해 다음과 같은 이점을 제공한다:
커피 주문 시스템에서 기본 커피에 다양한 옵션(우유, 시럽 등)을 추가할 수 있다.
데코레이터 패턴을 사용하면 기본 커피 클래스를 변경하지 않고 옵션을 동적으로 추가할 수 있다.
Component
↑
ConcreteComponent ←──── Decorator
↑
ConcreteDecorator
이번 예시에서는 “커피와 추가 옵션”을 데코레이터 패턴으로 구현해보겠다.
// Component 인터페이스
interface Coffee {
String getDescription();
double getCost();
}
// ConcreteComponent 클래스
class BasicCoffee implements Coffee {
@Override
public String getDescription() {
return "기본 커피";
}
@Override
public double getCost() {
return 2.0; // 기본 커피 가격
}
}
// Decorator 추상 클래스
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
}
// ConcreteDecorator 클래스
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", 우유";
}
@Override
public double getCost() {
return super.getCost() + 0.5; // 우유 추가 가격
}
}
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return super.getDescription() + ", 설탕";
}
@Override
public double getCost() {
return super.getCost() + 0.2; // 설탕 추가 가격
}
}
// 클라이언트 코드
public class Main {
public static void main(String[] args) {
Coffee coffee = new BasicCoffee();
System.out.println(coffee.getDescription() + " 가격: $" + coffee.getCost());
// 우유 추가
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + " 가격: $" + coffee.getCost());
// 설탕 추가
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() + " 가격: $" + coffee.getCost());
}
}
기본 커피 가격: $2.0
기본 커피, 우유 가격: $2.5
기본 커피, 우유, 설탕 가격: $2.7
데코레이터 패턴(Decorator Pattern)은 상속보다 유연한 대안으로, 객체의 동작을 확장하고 수정할 때 매우 유용하다.
특히, 기능 조합이 다양한 시스템에서 코드를 단순화하고 유지보수를 용이하게 만든다.nn
아래 글에서 다른 디자인 패턴들을 확인할 수 있다.
디자인 패턴 모음