12. Decorator - 장식물과 내용물을 동일시 한다
12. Decorator - 장식물과 내용물을 동일시 한다
데코레이터 패턴(Decorator Pattern)은 객체 지향 디자인 패턴 중 하나로, 객체에 동적으로 추가 기능을 부여하거나 변경할 수 있도록 하는 구조적 패턴입니다. 이 패턴을 사용하면 기본 객체의 구조를
변경하지 않고 기능을 확장할 수 있으며, 서브클래스의 생성을 피하고 복잡한 클래스 계층 구조를 방지할 수 있습니다.
데코레이터 패턴은 다음과 같은 구성 요소로 이루어집니다:
Component: 데코레이터 패턴의 핵심 인터페이스입니다. 이 인터페이스는 기본 객체와 데코레이터에 대한 추상화를 제공합니다.
ConcreteComponent: Component 인터페이스를 구현한 구체적인 객체입니다. 이 객체에 새로운 기능을 추가하려는 대상이 됩니다.
Decorator: Component 인터페이스를 구현하고, 데코레이터의 역할을 하는 추상 클래스입니다. 데코레이터 클래스는 실제로 구체적인 데코레이터 객체의 기능을 추가하는 역할을 합니다.
ConcreteDecorator: Decorator 클래스를 상속받아 실제 기능을 추가하고 확장하는 구체적인 데코레이터입니다. 이 클래스는 기본 객체에 대한 참조를 가지며, 해당 객체에 추가적인 동작을
수행하거나 변형시킵니다.
데코레이터 패턴의 주요 아이디어는, 여러 데코레이터를 조합해 기본 객체에 적용할 수 있다는 것입니다. 이를 통해 객체의 동작을 동적으로 변경하거나 확장할 수 있으며, 이러한 변경은 런타임에 이루어집니다. 이로써 기본
객체의 클래스 계층 구조를 확장하지 않고도 유연한 기능 확장을 할 수 있습니다.
데코레이터 패턴은 Java에서 자주 활용되며, 입·출력 스트림 처리, 그래픽 라이브러리, 웹 프레임워크 등 다양한 곳에서 활용됩니다. 이 패턴을 사용하면 코드 유지보수와 확장성을 향상시킬 수 있습니다.
예제
데코레이터 패턴의 예제 코드를 Java로 제공하겠습니다. 이 예제에서는 커피 주문 시 커피에 여러 추가 옵션을 데코레이션하는 간단한 시나리오를 다룰 것입니다.
- Component 인터페이스 (커피) 정의:
public interface Coffee {
double cost();
String getDescription();
}
- ConcreteComponent 구현 (기본 커피) :
public class SimpleCoffee implements Coffee {
@Override
public double cost() {
return 2.0;
}
@Override
public String getDescription() {
return "Simple Coffee";
}
}
- Decorator 추상 클래스 정의:
public abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee decoratedCoffee) {
this.decoratedCoffee = decoratedCoffee;
}
public double cost() {
return decoratedCoffee.cost();
}
public String getDescription() {
return decoratedCoffee.getDescription();
}
}
- ConcreteDecorator 구현 (옵션 추가) :
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
@Override
public double cost() {
return super.cost() + 0.5;
}
@Override
public String getDescription() {
return super.getDescription() + ", Milk";
}
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
@Override
public double cost() {
return super.cost() + 0.2;
}
@Override
public String getDescription() {
return super.getDescription() + ", Sugar";
}
}
- 클라이언트 코드:
public class CoffeeShop {
public static void main(String[] args) {
Coffee simpleCoffee = new SimpleCoffee();
System.out.println("Cost: " + simpleCoffee.cost() + ", Ingredients: " + simpleCoffee.getDescription());
Coffee milkCoffee = new MilkDecorator(simpleCoffee);
System.out.println("Cost: " + milkCoffee.cost() + ", Ingredients: " + milkCoffee.getDescription());
Coffee sweetCoffee = new SugarDecorator(milkCoffee);
System.out.println("Cost: " + sweetCoffee.cost() + ", Ingredients: " + sweetCoffee.getDescription());
}
}
이 예제에서, CoffeeDecorator
클래스를 통해 여러 옵션을 커피에 추가할 수 있으며, 기본 커피를 여러 레벨의 데코레이터를 통해 커스터마이징할 수 있습니다. 결과적으로 커피의 비용과 설명이 동적으로
변경됩니다.