반응형
데코레이터 패턴은 객체에 동적으로 새로운 기능을 추가할 수 있는 구조적 디자인 패턴입니다. 이 패턴은 상속을 사용하지 않고도 객체의 행동을 확장할 수 있기 때문에 유연하고 확장성 있는 코드를 작성할 수 있습니다.
1. 데코레이터 패턴이란?
- 동적으로 객체에 새로운 기능을 추가하는 방법을 제공하는 디자인 패턴입니다.
- 클래스 상속 대신 조합(Composition)을 사용하여 객체의 기능을 확장합니다.
- 기능 추가 시 코드 재사용성과 유연성이 높아집니다.
2. 데코레이터 패턴의 구조
데코레이터 패턴의 주요 구성 요소는 다음과 같습니다:
- Component: 기본 인터페이스나 추상 클래스입니다.
- ConcreteComponent: 기본 기능을 구현한 구체 클래스입니다.
- Decorator: Component를 구현하는 추상 클래스이며, 기능을 확장하는 데 사용됩니다.
- ConcreteDecorator: 기능을 추가하는 구체 데코레이터 클래스입니다.
클래스 다이어그램
+------------------+
| Component |
|------------------|
| + operation() |
+------------------+
^
|
+------------------+
| ConcreteComponent|
|------------------|
| + operation() |
+------------------+
^
|
+------------------+
| Decorator |
|------------------|
| - component |
| + operation() |
+------------------+
^
|
+-------------------+
| ConcreteDecorator |
|-------------------|
| + operation() |
+-------------------+
3. 데코레이터 패턴 예제 코드
아래는 Java를 사용해 데코레이터 패턴을 구현한 예제입니다.
예제 설명
- Component: 기본 인터페이스로
Coffee
를 정의합니다. - ConcreteComponent: 기본 커피인
SimpleCoffee
를 정의합니다. - Decorator: 커피에 추가적인 기능(설탕, 우유 등)을 더할 수 있는 데코레이터입니다.
- ConcreteDecorator: 기능을 추가하는 구체 클래스입니다 (설탕 추가, 우유 추가 등).
코드
// Component: 기본 인터페이스
interface Coffee {
String getDescription();
double getCost();
}
// ConcreteComponent: 기본 커피
class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "Simple Coffee";
}
@Override
public double getCost() {
return 5.0;
}
}
// Decorator: 데코레이터 추상 클래스
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getDescription() {
return coffee.getDescription();
}
@Override
public double getCost() {
return coffee.getCost();
}
}
// ConcreteDecorator: 우유 추가 기능
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Milk";
}
@Override
public double getCost() {
return coffee.getCost() + 1.5;
}
}
// ConcreteDecorator: 설탕 추가 기능
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Sugar";
}
@Override
public double getCost() {
return coffee.getCost() + 0.5;
}
}
// 클라이언트 코드
public class DecoratorPatternExample {
public static void main(String[] args) {
Coffee simpleCoffee = new SimpleCoffee();
System.out.println(simpleCoffee.getDescription() + " | Cost: $" + simpleCoffee.getCost());
// 우유 추가
Coffee milkCoffee = new MilkDecorator(simpleCoffee);
System.out.println(milkCoffee.getDescription() + " | Cost: $" + milkCoffee.getCost());
// 설탕 추가
Coffee sugarMilkCoffee = new SugarDecorator(milkCoffee);
System.out.println(sugarMilkCoffee.getDescription() + " | Cost: $" + sugarMilkCoffee.getCost());
}
}
출력 결과
Simple Coffee | Cost: $5.0
Simple Coffee, Milk | Cost: $6.5
Simple Coffee, Milk, Sugar | Cost: $7.0
4. 데코레이터 패턴의 사용 사례
- Java I/O 라이브러리
InputStream
,BufferedInputStream
,DataInputStream
등에서 데코레이터 패턴이 사용됩니다.
- GUI 프레임워크
- 사용자 인터페이스 구성 시 여러 컴포넌트에 기능을 동적으로 추가할 때 활용됩니다.
- 기능 확장이 필요한 객체
- 객체를 수정하지 않고 기능을 추가하거나 변경해야 할 때 유용합니다.
5. 결론
데코레이터 패턴은 상속 대신 조합을 사용해 기능을 확장하는 패턴으로, 객체에 동적으로 새로운 기능을 추가할 수 있습니다. 이를 통해 코드의 유연성과 확장성이 높아지며, Java I/O와 같은 다양한 실무 사례에서도 널리 사용되고 있습니다.
함께 보면 좋은 내용
이번 포스팅이 데코레이터 패턴을 이해하는 데 도움이 되었기를 바랍니다!
반응형
'JAVA > JAVA Design Pattern' 카테고리의 다른 글
JAVA 퍼사드(Facade) 패턴, 복잡한 시스템을 단순화하는 방법 (0) | 2024.12.27 |
---|---|
JAVA 접근 제어를 위한 프록시(Proxy) 패턴 (0) | 2024.12.26 |
JAVA 어댑터(Adapter) 패턴 (0) | 2024.12.24 |
JAVA - 프로토타입(Prototype) 패턴 (0) | 2024.12.23 |
빌더(Builder) 패턴 (0) | 2024.12.22 |