[디자인 패턴][구조 패턴] 장식자 패턴(Decorator Pattern)
Updated:
1. 개요
객체에 동적으로 새로운 책임을 추가할 수 있도록 하는 패턴
장식자 패턴(Decorator Pattern)은 구조 패턴(Structural Pattern)의 한 종류로, 서브클래스를 구현하지 않고도, 기존의 클래스에 동적으로 새로운 기능을 추가할 수 있도록 하는 패턴이다. 기존의 클래스를 둘러싸서 사용자의 요청을 가로채고, 추가적인 작업을 한 후 기존 클래스로 전달해준다.
2. 구조 패턴(Structural Pattern)
2-1. 구조 패턴이란?
구조 패턴이란 작은 클래스들의 상속과 합성을 통해 더 큰 클래스를 생성하는 방법을 제공하는 패턴으로, 독립적으로 개발한 클래스들을 마치 하나인 것 처럼 사용할 수 있다.
2-2. 구조 패턴 종류
3. 구성
[출처 : GoF의 디자인 패턴]
-
Component : 공통의 기능을 정의한 인터페이스
-
ConcreteComponent : Component 인터페이스 구현 클래스
-
Decorator : Component 인터페이스를 만족하면서 추가할 기능을 정의한 추상 클래스
-
ConcreteDecorator : Component에 새롭게 추가할 기능을 구현한 클래스
4. 예제 코드
케이크를 만든다고 가정해보자. 기본적으로 빵을 굽고 생크림을 바르면 케이크가 완성되고, 딸기나 블루베리를 추가할 수도 있다. 딸기나 블루베리를 추가할 때 Decorator Pattern을 활용할 수 있다.
4-1. Component
[Cake.java]
1
2
3
4
public interface Cake {
void makeCake();
}
4-2. ConcreteComponent
[DefaultCake.java]
1
2
3
4
5
6
7
8
public class DefaultCake implements Cake {
@Override
public void makeCake() {
System.out.println("Baking");
System.out.println("Add cream");
}
}
4-3. Decorator
[CakeDecorator.java]
1
2
3
4
5
6
7
8
abstract class CakeDecorator implements Cake {
protected Cake decoratedCake;
public CakeDecorator(Cake decoratedCake) {
this.decoratedCake = decoratedCake;
}
}
4-4. ConcreteDecorator
[BlueberryCake.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class BlueberryCake extends CakeDecorator {
public BlueberryCake(Cake decoratedCake) {
super(decoratedCake);
}
@Override
public void makeCake() {
decoratedCake.makeCake();
addBlueberry();
}
public void addBlueberry() {
System.out.println("Add blueberry");
}
}
Line 9 : 기존에 정의된 기능 수행
Line 10 : 새로운 기능 추가
[StrawberryCake.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class StrawberryCake extends CakeDecorator {
public StrawberryCake(Cake decoratedCake) {
super(decoratedCake);
}
@Override
public void makeCake() {
decoratedCake.makeCake();
addStrawberry();
}
public void addStrawberry() {
System.out.println("Add strawberry");
}
}
Line 9 : 기존에 정의된 기능 수행
Line 10 : 새로운 기능 추가
5. 테스트
[Clinet.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Client {
public static void main(String[] args) {
Cake cake = new DefaultCake();
cake.makeCake();
System.out.println("----------");
Cake blueberryCake = new BlueberryCake(new DefaultCake());
blueberryCake.makeCake();
System.out.println("----------");
Cake strawberryCake = new StrawberryCake(new DefaultCake());
strawberryCake.makeCake();
}
}
[실행 결과]
6. 특징
-
유연한 설계 : 새로운 기능의 추가/삭제가 런타임 시점에 가능
-
객체 수의 증가 : 작은 단위의 객체들이 계속 생성되어 객체 수정의 과정이 복잡해짐
7. Composite vs Decorator vs Proxy
-
Composite Pattern
- 관련된 객체들을 하나의 인터페이스로 관리
-
Decorator Pattern
- 상속 없이 동적으로 새로운 기능 추가
-
Proxy Pattern
- 기능을 제공하는 대상에 대한 참조를 직접 관리하지 않음
Leave a comment