본문 바로가기

프로그래밍/DesignPattern-C#

데코레이터(Decorator) 패턴

데코레이터(Decorator) 패턴

개별 클래스가 단일 책임(Single Responsibility)을 가질 수 있도록 하기에 매우 적합한 패턴이다. 클래스는 종종 다른 클래스에 책임을 위임할 명확한 방법을 찾지 못하고 혼자서 너무 많은 일들을 수행할 때가 있다. 이러면 클래스가 맡은 책임들이 서로 깊은 관련이 있어 보인다. 

데코레이터 패턴의 가장 기본적인 전제는 각 데코레이터 클래스가 어떤 타입에 대한 계약을 만족함과 동시에 생성자 매개변수를 통해 자신이 데코레이트할 하나 혹은 그 이상의 데코레이터 객체들을 받아들인다는 점이다. 이 패턴은 특정 인터페이스를 구현하는 기존 클래스에 새로운 기능을 추가할 수 있는데, 이때 (클라이언트가 알지 못하도록) 데코레이터를 이용해 해당 클래스가 여전히 필요한 인터페이스를 구현하고 있는 것처럼 보이게 할 수 있다는 점에서 유용하게 활용한다. 

데코레이터 패턴의 활용의 예 - 통상적으로 사용하는 방법 

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
69
//...
namespace DesignPattern.Decorator.Basic
{
    public interface IComponent
    {
        void Something();
    }
}
 
//...
namespace DesignPattern.Decorator.Basic
{
    public class ConcreteComponent : IComponent
    {
        public void Something()
        {
            Console.WriteLine("ConcreteComponent Class - Something()");
        }
    }
}
 
//...
namespace DesignPattern.Decorator.Basic
{
    public class DecoratorComponent : IComponent
    {
        private readonly IComponent decoratoredComponent;
 
        public DecoratorComponent(IComponent decoratoredComponent)
        {
            this.decoratoredComponent = decoratoredComponent;
        }
 
        public void Something()
        {
            SomethingElse();
            decoratoredComponent.Something();
        }
 
        private void SomethingElse()
        {
            Console.WriteLine("DecoratorComponent Class - SomethingElse()");
        }
    }
}
 
//...
namespace DesignPattern.Decorator.Basic
{
    class DecoratorProgram
    {
        static IComponent component;
 
        static void Main(string[] args)
        {
            component = new DecoratorComponent(new ConcreteComponent());
            component.Something();
            Console.WriteLine("DecoratorProgram.cs - End");
        }
    }
}
 
 
/* 결과
    DecoratorComponent Class - SomethingElse()
    ConcreteComponent Class - Something()
    DecoratorProgram.cs - End
*/
cs

클라이언트는 IComponent 인터페이스 타입의 멤버 변수를 정의하고 있기 때문에 이 변수에는 데코레이트된 타입(즉, DecoratorComponent타입)을 대입해도 되고 그렇지 않은 타입(ConcreteComponent타입)을 대입해도 된다. 클라이언트 입장에서는 자신이 어떤 타입을 사용하고 있는지에 대해서는 따로 기억해 둘 필요없이 두 타입을 모두 동일한 IComponent 인터페이스 타입으로 취급하면 된다. 


'프로그래밍 > DesignPattern-C#' 카테고리의 다른 글

컴포지트(Composite) 패턴  (0) 2019.01.31