Decorator Pattern
객체를 장식하는 형식으로 실행 중에 클래스를 꾸미는 패턴이다.
원래 클래스의 코드는 전혀 바꾸지 않고도 객체에 새로운 임무를 부여할 수도 있다.
( 즉, 부모클래스를 건드리지않고, 원하는 함수를 추가할 수 있다. 이래서 쓰는것임)
1. Decorator Pattern의 정의
데코레이터 패턴에서는 객체에 추가적인 요건을 동적으로 첨가한다.
데코레이터는 자식클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.
데코레이터 패턴에서는 객체에 추가적인 요건을 동적으로 첨가한다.
데코레이터는 자식클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.
2. Decorator Pattern의 특징
1) 데코레이터의 부모클래스는 자신이 장식하고 있는 객체의 부모클래스와 같으며, 한 객체를 여러 개의 데코레이터로 감쌀 수 있다.
2) 또한 데코레이터는 자신이 감싸고 있는 객체와 같은 부모클래스를 가지고 있기 때문에 원래 객체가 들어갈 자리에 데코레이터 객체를 집어넣어도 상관 없다.(이게 포인트! 클래스 다이어그램을 보고 이해할수 있어야함)
데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 것 외에 원하는 추가적인 작업을 수행할 수 있고 객체는 언제든지 감쌀 수 있기 때문에 실행에 필요한 데코레이터를 마음대로 적용할 수 있다.
1) 데코레이터의 부모클래스는 자신이 장식하고 있는 객체의 부모클래스와 같으며, 한 객체를 여러 개의 데코레이터로 감쌀 수 있다.
2) 또한 데코레이터는 자신이 감싸고 있는 객체와 같은 부모클래스를 가지고 있기 때문에 원래 객체가 들어갈 자리에 데코레이터 객체를 집어넣어도 상관 없다.(이게 포인트! 클래스 다이어그램을 보고 이해할수 있어야함)
데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 것 외에 원하는 추가적인 작업을 수행할 수 있고 객체는 언제든지 감쌀 수 있기 때문에 실행에 필요한 데코레이터를 마음대로 적용할 수 있다.
3. Decorator Pattern의 클래스 다이어그램
Component
Component
나의 해석:
우리가 쓰는것은 concreateDecoratorA,B,C,D....등등 이런 클래스이다.
이런 클래스에 어떤 행동같은것을 추가하려면 보통은 상속을 이용해서 부모클래스에 추가해주는게 보통이다.
근데, 너무 많은 자식클래스가 있으면 부모클래스에 쓸데없는 멤버변수들이 자꾸 추가되는게 불만이다!!!
그래서 실행중에 동적할당을 이용해서 데코레이션을 해줄 수 있는 패턴이 있는데 이가 데코레이션 패턴이다!!!!
기본상속개념을 위해 ConcreateComponent 같은 클래스로 자식클래스를 만들어준다.
A,B,C,D...이런클래스에서 Concreateponent 포인터를 하나 가지고있다.
이 포인터를 가지고 꾸며주기가 가능한 것이다. ( 덮어쓰기 개념을 이용 )
A,B,C,D 에서 행동을 한 후 레퍼런스를 계속 넘겨주는 식으로 하면 된다.
A,B,C,D에 반드시 정의되야하는 함수들이 있으므로, 순수가상함수를 만들어주기위한 Decorator란 클래스가 필요
그리고, Decorator에서 Concreateponent를 계속적으로 받아줘야하므로 둘은 같은 부모로 부터 상속받은 클래스여야한다. 그래서 최상위 Component 클래스가 있는것이다.
이해되나?~
이해하고 보니 상속개념을 역으로 이용한 것 같다는 느낌 ! ( is-a 관계가 아닌 상속의 원리만 이용한것이다! )
즉, "부모포인터는 자식을 받을 수 있다"를 이용함 ㅎㅎㅎ
다형성을 아주 잘 이용한 설계라고 볼수 있겠다.
우리가 쓰는것은 concreateDecoratorA,B,C,D....등등 이런 클래스이다.
이런 클래스에 어떤 행동같은것을 추가하려면 보통은 상속을 이용해서 부모클래스에 추가해주는게 보통이다.
근데, 너무 많은 자식클래스가 있으면 부모클래스에 쓸데없는 멤버변수들이 자꾸 추가되는게 불만이다!!!
그래서 실행중에 동적할당을 이용해서 데코레이션을 해줄 수 있는 패턴이 있는데 이가 데코레이션 패턴이다!!!!
기본상속개념을 위해 ConcreateComponent 같은 클래스로 자식클래스를 만들어준다.
A,B,C,D...이런클래스에서 Concreateponent 포인터를 하나 가지고있다.
이 포인터를 가지고 꾸며주기가 가능한 것이다. ( 덮어쓰기 개념을 이용 )
A,B,C,D 에서 행동을 한 후 레퍼런스를 계속 넘겨주는 식으로 하면 된다.
A,B,C,D에 반드시 정의되야하는 함수들이 있으므로, 순수가상함수를 만들어주기위한 Decorator란 클래스가 필요
그리고, Decorator에서 Concreateponent를 계속적으로 받아줘야하므로 둘은 같은 부모로 부터 상속받은 클래스여야한다. 그래서 최상위 Component 클래스가 있는것이다.
이해되나?~
이해하고 보니 상속개념을 역으로 이용한 것 같다는 느낌 ! ( is-a 관계가 아닌 상속의 원리만 이용한것이다! )
즉, "부모포인터는 자식을 받을 수 있다"를 이용함 ㅎㅎㅎ
다형성을 아주 잘 이용한 설계라고 볼수 있겠다.
4. Decorator Pattern의 구성
A. 각 구성요소는 직접 쓰일 수도 있고 데코레이터로 감싸져서 쓰일 수도 있다.
B. ConcreteComponent에 새로운 행동을 동적으로 추가하게 된다.
C. 각 데코레이터 안에는 Component 객체가 들어있다.
즉, 데코레이터에는 구성요소에 대한 레퍼런스가 들어있는 인스턴스 변수가 있다. D. Decorator는 자신이 장식할 구성요소와 같은 인터페이스 또는 추상 클래스를 구현한다.
A. 각 구성요소는 직접 쓰일 수도 있고 데코레이터로 감싸져서 쓰일 수도 있다.
B. ConcreteComponent에 새로운 행동을 동적으로 추가하게 된다.
C. 각 데코레이터 안에는 Component 객체가 들어있다.
즉, 데코레이터에는 구성요소에 대한 레퍼런스가 들어있는 인스턴스 변수가 있다. D. Decorator는 자신이 장식할 구성요소와 같은 인터페이스 또는 추상 클래스를 구현한다.
E. Decorator는 Component의 상태를 확장할 수 있다.
F. ConcreteDecorator에는 그 객체가 장식하고 있는 것(데코레이터가 감싸고 있는 Component 객체)을 위한 인터페이스 변수 가 있다.
G. 데코레이터에서 새로운 메소드를 추가할 수도 있다.
하지만 일반적으로 새로운 메소드를 추가하는 대신 Component에 원래 있던 메소드를 호출하기 전, 또는 후에 별도의 작업 을 처리하는 방식으로 새로운 기능을 추가한다.
F. ConcreteDecorator에는 그 객체가 장식하고 있는 것(데코레이터가 감싸고 있는 Component 객체)을 위한 인터페이스 변수 가 있다.
G. 데코레이터에서 새로운 메소드를 추가할 수도 있다.
하지만 일반적으로 새로운 메소드를 추가하는 대신 Component에 원래 있던 메소드를 호출하기 전, 또는 후에 별도의 작업 을 처리하는 방식으로 새로운 기능을 추가한다.
5. Decorator Pattern의 OCP(Open-Closed Principle) 디자인 원칙
OCP(Open-Closed Principle)이란 ?
클래스는 확장에 대해서는 열려 있어야 하지만 코드 변경에 대해서는 닫혀 있어야 한다는 뜻으로 기존 코드는 건드리지 않은 채로 확장을 통해서 새로운 행동을 간단하게 추가할 수 있도록 코드의 수정을 허용하는 것이다. 새로운 기능을 추가하는 데 있어서 매우 유연해서 급변하는 주변 환경에 잘 적응할 수 있으면서도 강하고 튼튼한 디자인을 만들 수 있다.
OCP(Open-Closed Principle)이란 ?
클래스는 확장에 대해서는 열려 있어야 하지만 코드 변경에 대해서는 닫혀 있어야 한다는 뜻으로 기존 코드는 건드리지 않은 채로 확장을 통해서 새로운 행동을 간단하게 추가할 수 있도록 코드의 수정을 허용하는 것이다. 새로운 기능을 추가하는 데 있어서 매우 유연해서 급변하는 주변 환경에 잘 적응할 수 있으면서도 강하고 튼튼한 디자인을 만들 수 있다.
6. Decorator Patternd의 장단점
장점: 데코레이터 패턴은 기본적인 데이터에 첨가할 데이터가 다양하고 일정하지 않을 때 효율적이다.
단점: 데코레이터 패턴을 사용하면 자잘한 객체들이 매우 많이 추가될 수 있고, 데코레이터를 너무 많이 사용하면 코드가 필요 이상으로 복잡해 질 수 도 있다.
( 가독성이 떨어진다. 일단 이게 데코레이션 패턴인지 분석을 해야하니까~ )
장점: 데코레이터 패턴은 기본적인 데이터에 첨가할 데이터가 다양하고 일정하지 않을 때 효율적이다.
단점: 데코레이터 패턴을 사용하면 자잘한 객체들이 매우 많이 추가될 수 있고, 데코레이터를 너무 많이 사용하면 코드가 필요 이상으로 복잡해 질 수 도 있다.
( 가독성이 떨어진다. 일단 이게 데코레이션 패턴인지 분석을 해야하니까~ )
--------------------------------------------------------------------------------------------------------------
제가 보는 책(head first design patterns)에서는 데코레이션 패턴을 커피 예를 들어서 설명을 했습니다.
커피집에 가면 커피가 굉장히 많은데 그 커피에 대한 클래스를 만들고 모든 재료, 기능들을 넣는 것 보단 커피 클래스 따로 재료 클래스 따로 만들고 있었습니다.
커피 클래스, 재료 클래스를 따로 만들게 되었을 때 서로 유기적으로 잘 묶기만 한다면 한 클래스에 모든 기능을 넣는 것 보단 당연히 구조적으로 좋겠죠?
데코레이션 패턴에서는 유기적으로 묶는 방법으로 "감싸"는 것을 선택했습니다.
위 클래스 다이어그램을 보시면 가장 상위에 Coffee 추상 클래스가 보입니다.
그 아래로 그것을 상속받는 Americano, Espresso, Cafelatte같은 클래스가 있습니다. ( 꾸며주는 클래스들~~~ )
또, Decorator라는 추상클래스가 있는데 이 클래스는 getDescription이라는 순수가상함수를 갖고 있습니다. ( 순수가상함수를 위해 만들어진 클래스 )
그래서 아래 재료들이 무조건 이 함수를 새로 정의하게 만들었습니다.
이 패턴의 시나리오는 위 소스에서 보는 것과 같이 원하는 커피 인스턴스를 생성하고 원하는 재료를 만들어서 서로에게 계속 참조를 시킨다는 것입니다. (감싼다는 의미가 이것입니다.)
사용자가 getDescription함수를 호출하거나 cost 함수를 호출하면 제어가 계속 참조하는 곳으로 올라가게 됩니다.
(아래 소스 참조)
이런 식으로 사용자는 예전부터 있던 클래스를 하나도 수정하지 않고 단지 "감싸"서 예전 클래스에 새로운 기능을 부여하는 것이 가능합니다.
출저:http://cafe.naver.com/ccjmaster.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=530&디자인패턴중에 데코레이션 패턴을 공부해보았다.
첨에 뭐가 뭔지 몰라서 완전 헷갈렸다.
하지만, 완벽분석 후 내 나름대로 정리해보았다.
출저는 저기이고, 회색 네모가 내가 정리한 내용이다.
댓글 없음:
댓글 쓰기