도찐개찐
[코드디자인패턴-JAVA] Decorator Pattern 본문
Decorator Pattern
- 동적으로 추가하거나 수정 할 필요가 있을때 사용하는 구조 패턴.
- 기본기능에 추가 기능을 연결해 확장성을 향상시키고 코드 중복을 줄일 수 있게 해줍니다.
- 주로 유연하고 재사용 가능한 코드를 작성 할 때 유용합니다.
사용시점
- 여러 기능의 조합이 필요 할 때, 여러 기능을 동적으로 추가하거나 제거할 필요가 있을 때.
- 확장이 예상 되는 경우에, 기능을 쉽게 추가하거나 변경 할 수 있어야 할 때.
- 기존 클래스를 수정하지 않고 기능을 추가하거나 변경하고 싶을 때.
종류
- Concrete Component: 실제 기본 기능을 정의하는 클래스입니다.
- Abstract Decorator: 모든 데코레이터가 구현해야 하는 인터페이스나 추상 클래스입니다.
- Concrete Decorator: Abstract Decorator를 확장하여, 특정 기능을 추가하는 클래스입니다.
예시:
기본 차량 가격을 계산하는 시스템에서 추가 옵션을 동적으로 추가 할 수 있는 경우 Decorator Pattern이 적합 합니다.
차량은 기본 Component이고, 각각의 추가 옵션(예: 에어컨, 합성 가죽 시트 등)은 Concrete Decorator 입니다.
객체의 확장을 쉽게 만들어 주며, 개방/폐쇄 원칙(Open/closed principle)을 따릅니다.
여기서 "개방"은 확장에 열려있어야 함을 의미하고, "폐쇄"는 기존 코드 수정 없이 확장이 가능해야 함을 의미 합니다.
public interface Beverage {
String getDescription();
double cost();
}
1. Concrete Component(기본 기능을 정의하는 클래스)
public class Coffee implements Beverage {
public String getDescription() {
return "Coffee";
}
public double cost() {
return 5.0;
}
}
2. Abstract Decorator(데코레이터가 구현해야 하는 인터페이스)
public abstract class BeverageDecorator implements Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
3. Concrete Decorator(특정 기능을 추가하는 클래스)
public class MilkDecorator extends BeverageDecorator {
public MilkDecorator(Beverage beverage) {
super(beverage);
}
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
public double cost() {
return beverage.cost() + 1.0;
}
}
Beverage beverage = new Coffee();
Beverage milkBeverage = new MilkDecorator(beverage);
System.out.println(beverage.getDescription() + " $" + beverage.cost());
System.out.println(milkBeverage.getDescription() + " $" + milkBeverage.cost());
Coffee $5.0
Coffee, Milk $6.0
장점
- 유연성: 기존 클래스를 수정하지 않고 기능을 확장할 수 있으므로 유연한 설계가 가능 합니다.
- 재사용성: 데코레이터를 여러 객체에 대해 재사용할 수 있습니다.
- 개방/폐쇄 원칙을 따름: 기존 코드를 수정하지 않고 새로운 기능을 쉽게 추가할 수 있습니다.
단점
- 복잡성 증가: 많은 데코레이터 클래스가 필요한 경우, 코드 복잡도가 높아짐.
- 유지보수 어려움 : 데코레이터 체인이 길어질수록 디버깅이나 유지보수가 어려워 질수 있습니다.
데이터 패턴은 객체의 책임을 동적으로, 투명하게 추가할 때 사용되며, 장식이 필요한 다양한 경우에 적용할 수 있습니다.
대표 사례
- 자바의 I/O 클래스: 자바의 java.io 패키지에서는 데코레이터 패턴이 광범위하게 사용됩니다. 예를 들어, BufferedReader, BufferedWriter 등의 클래스는 기본 입력/출력 스트림에 버퍼링 기능을 추가하는 데코레이터 역할을 합니다. 다양한 데코레이터를 조합해 원하는 기능을 효율적으로 확장할 수 있습니다.
- GUI 컴포넌트: 그래픽 사용자 인터페이스(GUI) 라이브러리에서 데코레이터 패턴은 컴포넌트에 여러 가지 시각적 효과나 동작을 추가할 때 사용될 수 있습니다. 예를 들어, 스크롤 바, 테두리, 그림자 등의 요소를 독립적으로 추가하거나 제거할 수 있습니다.
- 웹 서버의 미들웨어: 웹 서버에서 요청과 응답을 처리하는 미들웨어에서도 데코레이터 패턴이 사용될 수 있습니다. 로깅, 인증, 압축, 캐싱 등의 기능을 각각의 데코레이터로 구현하면, 필요한 기능을 조합해 사용할 수 있으며 유지보수도 쉬워집니다.
- 커피 샵 메뉴 시스템: 데코레이터 패턴을 설명할 때 자주 사용되는 예시로, 커피나 다른 음료에 다양한 추가 토핑을 조합할 수 있는 시스템을 만들 때 적용할 수 있습니다. 각 토핑을 데코레이터로 구현하면, 다양한 조합의 메뉴를 효율적으로 관리할 수 있습니다.
728x90
'프로그래밍 > 코드디자인패턴' 카테고리의 다른 글
[코드디자인패턴-JAVA] Facade Pattern (0) | 2024.02.29 |
---|---|
[코드디자인패턴-JAVA] Factory Method Pattern (0) | 2024.02.29 |
[코드디자인패턴-JAVA] Observer Pattern (0) | 2024.02.29 |
[코드디자인패턴-JAVA] Singleton Pattern (0) | 2024.02.29 |
[코드디자인패턴-JAVA] State Pattern (0) | 2024.02.29 |
Comments