목차
1. 데코레이터 패턴이란?
데코레이터 패턴(Decorator Pattern)은 객체에 동적으로 추가적인 기능을 부여할 수 있는 디자인 패턴입니다. 기본적으로, 데코레이터 패턴은 기존 클래스에 기능을 추가하고 싶을 때 사용됩니다. 이는 상속 대신 구성(Composition)을 사용하여 동적으로 기능을 확장할 수 있게 해줍니다.
데코레이터 패턴 사용 이유:
- 객체의 기능을 동적으로 추가할 수 있습니다.
- 상속을 사용하지 않고 기존 코드 수정 없이 기능 확장이 가능합니다.
- 여러 기능을 조합하여 사용할 수 있습니다.
2. 데코레이터 패턴의 특징
- 기존 클래스를 변경하지 않고 기능을 추가할 수 있습니다.
- 데코레이터 클래스는 Coffee 객체를 포함하여 추가 기능을 구현합니다.
- 여러 데코레이터를 체인처럼 연결하여 기능을 확장할 수 있습니다.
- 유연한 구조로 기능을 쉽게 변경하고 확장할 수 있습니다.
3. 자바에서 데코레이터 패턴 구현하기
예시: 커피 주문 시스템
데코레이터 패턴을 이해하기 위해 커피 주문 시스템을 예시로 들어볼게요. 기본적으로 커피를 주문하면 기본적인 커피가 나오는데, 우유나 설탕 등을 추가할 수 있습니다. 이때, 각각의 추가 기능을 데코레이터로 구현할 수 있습니다.
1. 기본 커피 인터페이스
// 기본 커피 인터페이스
public interface Coffee {
String getDescription();
double cost();
}
Coffee 인터페이스는 커피의 기본적인 getDescription() 메서드(설명)와 cost() 메서드(가격)를 정의합니다.
2. 기본 커피 클래스
// 기본 커피 클래스
public class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "Simple Coffee";
}
@Override
public double cost() {
return 5.0; // 기본 커피 가격
}
}
SimpleCoffee 클래스는 Coffee 인터페이스를 구현한 기본 커피 클래스입니다. 기본적으로 "Simple Coffee"라는 설명과 5.0의 가격을 반환합니다.
3. 데코레이터 클래스
데코레이터 클래스는 Coffee 객체를 래핑하여 그 객체에 기능을 추가합니다.
// 커피 데코레이터 클래스 (추상 클래스)
public abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
public String getDescription() {
return decoratedCoffee.getDescription();
}
public double cost() {
return decoratedCoffee.cost();
}
}
CoffeeDecorator 클래스는 Coffee 인터페이스를 구현하며, 실제로 데코레이터가 기능을 추가할 객체를 decoratedCoffee 필드로 포함하고 있습니다. 그 후 getDescription()과 cost() 메서드를 오버라이드하여 기본 커피 기능을 그대로 사용하고, 추가적인 기능을 추가할 수 있게 됩니다.
4. 기능 추가: 우유와 설탕
우리는 이제 기본 커피에 우유와 설탕을 추가하는 데코레이터를 만들겠습니다.
// 우유 추가 데코레이터
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription() + ", Milk";
}
@Override
public double cost() {
return decoratedCoffee.cost() + 1.0; // 우유 추가 비용
}
}
MilkDecorator는 CoffeeDecorator 클래스를 상속받아 getDescription()과 cost() 메서드를 오버라이드하여 기본 커피에 Milk를 추가하고, 비용도 추가합니다.
// 설탕 추가 데코레이터
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription() + ", Sugar";
}
@Override
public double cost() {
return decoratedCoffee.cost() + 0.5; // 설탕 추가 비용
}
}
SugarDecorator도 비슷하게 getDescription()과 cost() 메서드를 오버라이드하여 설탕을 추가합니다.
5. 데코레이터 사용하기
이제 실제로 데코레이터 패턴을 어떻게 사용할 수 있는지 보겠습니다.
public class CoffeeShop {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee(); // 기본 커피 주문
System.out.println("Order 1: " + coffee.getDescription() + " Cost: " + coffee.cost());
// 우유 추가
coffee = new MilkDecorator(coffee);
System.out.println("Order 2: " + coffee.getDescription() + " Cost: " + coffee.cost());
// 설탕 추가
coffee = new SugarDecorator(coffee);
System.out.println("Order 3: " + coffee.getDescription() + " Cost: " + coffee.cost());
}
}
위 코드는 기본 커피에서 우유와 설탕을 동적으로 추가하는 방식입니다. 실행 결과는 다음과 같습니다.
Order 1: Simple Coffee Cost: 5.0
Order 2: Simple Coffee, Milk Cost: 6.0
Order 3: Simple Coffee, Milk, Sugar Cost: 6.5
4. 예제 코드 설명
- SimpleCoffee 클래스는 기본적인 커피를 나타냅니다. "Simple Coffee"라는 설명과 5.0의 가격을 반환합니다.
- CoffeeDecorator는 데코레이터 패턴의 핵심으로, 다른 데코레이터 클래스를 통해 커피에 기능을 추가할 수 있도록 합니다.
- MilkDecorator와 SugarDecorator는 기본 커피에 우유와 설탕을 각각 추가하는 클래스입니다.
- CoffeeShop 클래스에서 커피를 주문하고 데코레이터를 사용하여 동적으로 우유와 설탕을 추가합니다.
5. 데코레이터 패턴의 장점과 단점
장점
- 기능 확장이 유연합니다. 새로운 기능을 추가하려면 새로운 데코레이터 클래스를 추가하기만 하면 됩니다.
- 기존 코드 수정 없이 기능을 확장할 수 있어, 유지보수가 용이합니다.
- 여러 데코레이터를 조합하여 다양한 기능을 만들어낼 수 있습니다.
단점
- 데코레이터가 많아지면 클래스의 수가 증가하여 코드가 복잡해질 수 있습니다.
- 디버깅이 어려울 수 있습니다. 여러 데코레이터가 중첩되면, 문제를 추적하는 데 시간이 걸릴 수 있습니다.
6. 결론
데코레이터 패턴은 객체의 기능을 동적으로 확장할 수 있는 강력한 패턴입니다. 기존 코드를 변경하지 않고 기능을 추가할 수 있어, 유연하고 유지보수에 용이합니다. 다양한 기능을 조합하여 새로운 기능을 만들어낼 수 있기 때문에, 복잡한 시스템에서 매우 유용하게 사용될 수 있습니다.
자바에서 데코레이터 패턴을 구현할 때는 구성(Composition)을 활용하여 클래스를 조합하는 방식으로 동작합니다. 이를 통해 확장성과 유연성을 얻을 수 있습니다.
'Design Pattern with Java' 카테고리의 다른 글
8. 플라이웨이트 (Flyweight 패턴) - 메모리 최적화 디자인 패턴 (0) | 2025.01.17 |
---|---|
6. 전략 패턴(Strategy Pattern) (0) | 2025.01.15 |
5. 템플릿메소드 패턴(Template Method) (0) | 2025.01.15 |
4. Builder 패턴(from effective-java) (0) | 2025.01.07 |
4. builder 패턴(gof) (0) | 2025.01.07 |