본문 바로가기

PROGRAMMING/Design Pattern

[GoF] 데코레이터 (Decorator) 패턴

데코레이터 (Decorator) 패턴 구조 패턴

여러 객체의 참조 관계를 통해 객체의 기능을 동적으로 확장합니다.

 


블로그를 방문할 때 Powered by ~ 라는 글귀를 본 적이 있을 것이다. 이는 사용자가 작성했던 글이 해당 사이트에 의해 제공되었다는 의미이다. 그러므로, 지금 이 글은 'Powered by Tistory'이다. 만약 이 글이 네이버 블로그에서 작성되었다면 'Powered by NaverBlog'가 될 것이다.

사용자가 작성했던 글은 HTML로 작성된 텍스트 더미이나, 이것이 사이트로부터 제공되어지면 사이트가 가진 스타일시트(CSS)에 의해 글은 꾸며져 방문자에게 보여진다. 따라서 사용자가 작성했던 글은 같은 내용일지라도 서로 다른 사이트에 의해 다르게 꾸며진다. 여기서 사이트라는 개념은 데코레이터 패턴의 예시로 볼 수 있다.

객체의 기능을 확장하기 위한 상속은 명료하고 정적인 기능의 확장 방법이다. 하지만 상속의 정적인 특성은 기능의 동적인 조합(다양한 재료를 첨가하듯)에 대해서는 상속을 통해 수많은 경우의 수를 직접 정의해야 함으로 알맞지 않다. 그래서, 상속에 의한 기능의 확장의 대안으로써 데코레이터 패턴은 객체의 참조를 통해 객체의 기능을 동적으로 확장할 수 있다 (객체를 꾸며준다). 그래서 설령 같은 객체라 할지라도, 다른 데코레이터 객체에 의해 기능이 달라지게 된다.

또한, 데코레이터 객체는 객체와 동일한 인터페이스를 클라이언트에게 제공하기에 데코레이터 객체 자체를 해당 객체처럼 사용할수도 있고 데코레이터 객체가 인터페이스가 같은 데코레이터 객체를 참조하여 기능의 확장을 중첩적으로 수행할 수도 있다. 클라이언트에게 객체와 동일한 인터페이스를 제공한다는 점에 있어 프록시 (Proxy) 패턴과 유사하나, 데코레이터 패턴은 객체의 중개가 아닌 기능 확장이 목적이라는 것이 프록시 패턴과의 핵심적인 차이이다.

데코레이터 패턴을 이용한 기능의 확장은 객체로부터 독립적이며, 기능의 조합에 대응하기 위해 상위 클래스에 기능이 몰리는 현상을 완화시킬 수 있다. 하지만, 여러 객체의 생성을 통한 확장은 객체의 관리에 있어 다소 어려움이 발생할 수 있다.

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class PatternDecorator
{
    public interface IComponent
    {
        void Operate();
    }
 
    public class Component : IComponent
    {
        public void Operate()
        {
            Console.WriteLine("Operating Component");
        }
    }
 
    public abstract class Decorator : IComponent
    {
        protected IComponent _component;
 
        public Decorator(IComponent component)
        {
            _component = component;
        }
 
        public abstract void Operate();
    }
 
    public class DecoratorA : Decorator
    {
        public DecoratorA(IComponent component) : base(component)
        {
 
        }
 
        public override void Operate()
        {
            _component.Operate();
 
            Console.WriteLine("Powered by DecoratorA");
        }
    }
 
    public class DecoratorB : Decorator
    {
        public DecoratorB(IComponent component) : base(component)
        {
 
        }
 
        public override void Operate()
        {
            _component.Operate();
 
            Console.WriteLine("Powered by DecoratorB");
        }
    }
 
    public static void Main(string[] args)
    {
        IComponent decoratorA = new DecoratorA(new Component());
        IComponent decoratorB = new DecoratorB(decoratorA);
 
        decoratorA.Operate();
        Console.WriteLine();
 
        decoratorB.Operate();
    }
}
cs
1
2
3
4
5
6
7
Operating Component
Powered by DecoratorA
 
Operating Component
Powered by DecoratorA
Powered by DecoratorB
Press any key to continue . . .
cs

 

'PROGRAMMING > Design Pattern' 카테고리의 다른 글

[GoF] 경량 (Flyweight) 패턴  (0) 2019.03.09
[GoF] 파사드 (Facade) 패턴  (0) 2019.03.09
[GoF] 컴포지트 (Composite) 패턴  (0) 2019.03.09
[GoF] 브릿지 (Bridge) 패턴  (0) 2019.03.09
[GoF] 프록시 (Proxy) 패턴  (0) 2019.03.09