@Desc
: Decorator pattern은 Component의 기능을 유연하게 확장하기 위해 Sub Class를 이용하는 기법이다.
: "Component" 란 실제로 우리가 표현하기 원하는 원래의 객체를 의미하고,
: "Decorator" 는 그러한 Component들의 기능을 확장시켜주는 Wrapper Class로 이해할 수 있다.
: Decorator는 Component의 Sub Class로 구현되어 Component와 다형성을 형성하기 때문에,
: 마치 기능이 조금 추가되거나 변경된 Component 자체인 것처럼 여겨질 수 있다. 이러한 특성 때문에
: Decorator Pattern을 이용하면 원래의 Component의 기능을 유연하게 확장할 수 있게 된다.
: Decorator Pattern은 몇 가지 단점도 가지고 있는데,
: 하나는 남들이 이해하기 힘들 정도로 자잘한 클래스들이 엄청나게 추가될 수 있다는 것이다.
: 둘째는 특정 형식에 의존하는 코드에 Decorator를 적용하기엔 무리가 있다는 것이다.
: 셋째는 Decorator들이 많기 때문에 Component를 초기화하는 데 필요한 코드가 복잡해진다는 것이다.
: 마지막 단점은 "Factory Pattern" 이나 "Builder Pattern" 을 이용해서 보완 가능할 수 있다.
: 요약 결론하면,
: Decorator Pattern에서는 객체에 추가적인 요건을 동적으로 첨가한다.
: Decorator는 Sub Class를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.
@Example
1) Starbuzz Order System을 구현해 보고자 한다.
2) Starbuzz에는 HouseBlend, DarkRoast, Decaf, Espresso 등의 많은 음료(Beverage)가 있고,
3) 음료에는 Milk, Soy, Mocha, Whip 등 첨가물(Condiment)이 추가될 수 있다.
4) 쉽게 생각하면 Beverage라는 Super Class를 만들고 각 음료마다 Beverage 클래스를 상속할 수 있다.
5) 그리고 각 첨가물에 따른 비용 가감은 Super Class의 Cost() 함수 내에서 처리해야 할 것이다.
6) 그런데, 이 방식은 문제가 많다.
7) 첫째로 첨가물 가격이 바뀔 때마다 Cost() 함수를 계속 수정해야만 하고,
8) 첨가물 종류가 많아지면 Cost() 함수 내부 처리가 복잡해질 수 있다.
9) 만약 새로운 음료 Ice Tea가 출시되었다면 이런 경우 Whip에 대한 처리는 없어야 한다.
10) 상속을 받았기 때문에 Cost() 함수 내용을 그대로 전달받게 되는데, 이것을 변경할 순 있지만
11) 만약 이를 변경하려면 Overriding이 필요하고 이것은 Sub Class의 복잡성을 증가시킨다.
12) 나중에는 어떤 Class가 어떤 첨가물을 추가할 수 있는지 없는지가 혼란스러울 것이다.
13) 여기서 "OCP Principle" 이 사용될 수 있다.
14) Condiment Decorator 클래스를 만들고 Component의 추상클래스인 Beverage를 상속해보자.
15) 그리고 Component 객체를 Decorator에 구성(Composition)으로 추가한다.
16) 즉, Decorator를 생성할 때 Component를 Parameter로 하여 Composition 관계를 만든다.
17) 이렇게 되면 Decorator 동작 시 Component의 동작을 변경하지 않고 기능을 추가할 수 있다.
@Principle
" Open-Closed Principle " (OCP 원칙)
: 클래스는 확장에 대해서는 열려 있어야 하지만,
코드 변경에 대해서는 닫혀 있어야 한다.
: Decorator pattern은 Component의 기능을 유연하게 확장하기 위해 Sub Class를 이용하는 기법이다.
: "Component" 란 실제로 우리가 표현하기 원하는 원래의 객체를 의미하고,
: "Decorator" 는 그러한 Component들의 기능을 확장시켜주는 Wrapper Class로 이해할 수 있다.
: Decorator는 Component의 Sub Class로 구현되어 Component와 다형성을 형성하기 때문에,
: 마치 기능이 조금 추가되거나 변경된 Component 자체인 것처럼 여겨질 수 있다. 이러한 특성 때문에
: Decorator Pattern을 이용하면 원래의 Component의 기능을 유연하게 확장할 수 있게 된다.
: Decorator Pattern은 몇 가지 단점도 가지고 있는데,
: 하나는 남들이 이해하기 힘들 정도로 자잘한 클래스들이 엄청나게 추가될 수 있다는 것이다.
: 둘째는 특정 형식에 의존하는 코드에 Decorator를 적용하기엔 무리가 있다는 것이다.
: 셋째는 Decorator들이 많기 때문에 Component를 초기화하는 데 필요한 코드가 복잡해진다는 것이다.
: 마지막 단점은 "Factory Pattern" 이나 "Builder Pattern" 을 이용해서 보완 가능할 수 있다.
: 요약 결론하면,
: Decorator Pattern에서는 객체에 추가적인 요건을 동적으로 첨가한다.
: Decorator는 Sub Class를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.
@Example
1) Starbuzz Order System을 구현해 보고자 한다.
2) Starbuzz에는 HouseBlend, DarkRoast, Decaf, Espresso 등의 많은 음료(Beverage)가 있고,
3) 음료에는 Milk, Soy, Mocha, Whip 등 첨가물(Condiment)이 추가될 수 있다.
4) 쉽게 생각하면 Beverage라는 Super Class를 만들고 각 음료마다 Beverage 클래스를 상속할 수 있다.
5) 그리고 각 첨가물에 따른 비용 가감은 Super Class의 Cost() 함수 내에서 처리해야 할 것이다.
6) 그런데, 이 방식은 문제가 많다.
7) 첫째로 첨가물 가격이 바뀔 때마다 Cost() 함수를 계속 수정해야만 하고,
8) 첨가물 종류가 많아지면 Cost() 함수 내부 처리가 복잡해질 수 있다.
9) 만약 새로운 음료 Ice Tea가 출시되었다면 이런 경우 Whip에 대한 처리는 없어야 한다.
10) 상속을 받았기 때문에 Cost() 함수 내용을 그대로 전달받게 되는데, 이것을 변경할 순 있지만
11) 만약 이를 변경하려면 Overriding이 필요하고 이것은 Sub Class의 복잡성을 증가시킨다.
12) 나중에는 어떤 Class가 어떤 첨가물을 추가할 수 있는지 없는지가 혼란스러울 것이다.
13) 여기서 "OCP Principle" 이 사용될 수 있다.
14) Condiment Decorator 클래스를 만들고 Component의 추상클래스인 Beverage를 상속해보자.
15) 그리고 Component 객체를 Decorator에 구성(Composition)으로 추가한다.
16) 즉, Decorator를 생성할 때 Component를 Parameter로 하여 Composition 관계를 만든다.
17) 이렇게 되면 Decorator 동작 시 Component의 동작을 변경하지 않고 기능을 추가할 수 있다.
@Principle
" Open-Closed Principle " (OCP 원칙)
: 클래스는 확장에 대해서는 열려 있어야 하지만,
코드 변경에 대해서는 닫혀 있어야 한다.
@reference
: Head First Design Patterns
by Eric Freeman, Elisabeth Freeman, Kathy Sierra, Bert Bates, 1st Ed.
Decorator Pattern을 구현할 때는 Decorator가 상속할 Component Class에서 Destructor를 virtual로 선언해 주어야 한다. 그래야 Wrapping되어 있는 실제 객체의 Destructor를 호출하여 Memory Leak을 방지할 수 있다.
ReplyDelete