[Design Pattern] 데코레이터 패턴

Decorator Pattern

데코레이터 패턴이란 객체에 동적으로 새로운 기능을 확장할 수 있는 패턴이다.

활용성

  1. 동적으로 다른 객체에 영향을 주지 않고 각각의 객체에 새로운 책임을 추가하고 싶을 때
  2. 제거될 수 있는 책임을 부여하고 싶을 때
  3. 상속으로 서브클래스를 계속 만드는 방법이 생산적이지 못할 때

데코레이터 패턴 사용에 따른 결과

단순 상속보다 설계의 유연성 증대

데코레이터 패턴을 통해 런타임에 객체에 새로운 책임을 부여하고 삭제하는 일이 가능해진다.

클래스 계층의 상부측 클래스에 기능 누적 회피

데코레이터 패턴은 필요한 비용만 그 때 지불하는 방법을 제공한다. 그렇기 때문에 확장에도 유연하며 단순한 기능 누적이 아닌 기능 조합으로 이어진다.

데코레이터를 통해 작은 규모의 객체 다량 생성

데코레이터를 통해 유연한 확장과 런타임에 조합이라는 강점을 가질 수 있지만 많은 데코레이터가 정의되었을 때 이를 익히고 사용하는 과정이 어려워질 수 있다.

데코레이터

구조

데코레이터의 구조는 다음과 같다.

Decorator Pattern Diagram

C++ 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void DecoratorPattern::buildPlanePanel()
{
Panel* panel = new InstrumentPanel();
panel->show();
}

void DecoratorPattern::buildLedPanel()
{
Panel* panel = new LedPanelDecorator(new InstrumentPanel);
panel->show();
}

void DecoratorPattern::buildDistanceLedPanel()
{
Panel* panel = new DistancePanelDecorator(new LedPanelDecorator(new InstrumentPanel));
panel->show();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Panel
{
public:
virtual ~Panel() {};
virtual void show() = 0;
};

class InstrumentPanel : public Panel
{
public:
~InstrumentPanel() override {};

void show() override
{
std::cout<<"차량 계기판 표시"<<std::endl;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class PanelDecorator : public Panel
{
Panel* panel;
public:
PanelDecorator(Panel* panel) {
this->panel = panel;
}

~PanelDecorator() override {};

void show() override {
panel->show();
}
};

class LedPanelDecorator : public PanelDecorator
{
void getLedLights()
{
std::cout<<"계기판 LED 점등"<<std::endl;
}
public:
LedPanelDecorator(Panel* panel) : PanelDecorator(panel) {}

void show() override
{
PanelDecorator::show();
getLedLights();
}
};

class DistancePanelDecorator : public PanelDecorator
{
void getDistanceInfo()
{
std::cout<<"계기판 이동 거리 표시"<<std::endl;
}
public:
DistancePanelDecorator(Panel* panel) : PanelDecorator(panel) {}

void show() override
{
PanelDecorator::show();
getDistanceInfo();
}
};

java 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Client {
public static void main(String[] args) {
buildPlanePanel();
buildLedPanel();
buildDistanceLedPanel();
}

public static void buildPlanePanel() {
Panel panel = new InstrumentPanel();
panel.show();
}

public static void buildLedPanel() {
Panel panel = new LedPanelDecorator(new InstrumentPanel());
panel.show();
}

public static void buildDistanceLedPanel() {
Panel panel = new DistancePanelDecorator(new LedPanelDecorator(new InstrumentPanel()));
panel.show();
}
}
1
2
3
4
5
6
7
8
9
10
public interface Panel {
void show();
}

public class InstrumentPanel implements Panel{
@Override
public void show() {
System.out.println("차량 계기판 표시");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public abstract class PanelDecorator implements Panel{
protected Panel panel;

public PanelDecorator(Panel panel) {
this.panel = panel;
}
}

public class LedPanelDecorator extends PanelDecorator{
public LedPanelDecorator(Panel panel) {
super(panel);
}

@Override
public void show() {
panel.show();
getLedLights();
}

private void getLedLights() {
System.out.println("계기판 LED 점등");
}
}

public class DistancePanelDecorator extends PanelDecorator{
public DistancePanelDecorator(Panel panel) {
super(panel);
}

@Override
public void show() {
panel.show();
getDistanceInfo();
}

private void getDistanceInfo() {
System.out.println("계기판 이동 거리 표시");
}
}
Author: Song Hayoung
Link: https://songhayoung.github.io/2020/08/18/Design%20Pattern/DecoratorPattern/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.