SW/디자인 패턴

데코레이터 디자인 패턴 : 정의, 개념, 구조, 예시

얇은생각 2019. 9. 9. 07:30
반응형

의도

- 객체에 추가적인 책임을 동적으로 부여합니다. 데코레이터는 기능 확장을 위해 서브 클래스에 대한 유연한 대안을 제공합니다.

- 핵심 오브젝트를 클라이언트가 재귀적으로 랩핑하여 꾸미는 것

- 즉, 선물 포장, 상자에 넣고 상자를 포장합니다.




문제

런타임에 개별 객체에 동작 또는 상태를 추가하려고합니다. 정적이며 전체 클래스에 적용되므로 상속은 불가능합니다.




논의

사용자 인터페이스 툴킷에서 작업 중이고 창에 테두리 및 스크롤 막대 추가를 지원한다고 가정하십시오. 상속 계층 구조를 다음과 같이 정의 할 수 있습니다.


데코레이터 디자인 패턴 : 정의, 개념, 구조, 예시


그러나 데코레이터 패턴은 고객에게 원하는 "기능" 조합을 지정할 수있는 기능을 제공합니다.


Widget* aWidget = new BorderDecorator(

  new HorizontalScrollBarDecorator(

    new VerticalScrollBarDecorator(

      new Window( 80, 24 ))));

aWidget->draw();


이 유연성은 다음과 같은 디자인으로 달성 할 수 있습니다


데코레이터 디자인 패턴 : 정의, 개념, 구조, 예시


커스텀 객체를 생성하기 위한 캐스케이딩 (또는 연쇄) 기능의 또 다른 예는 다음과 같습니다.


Stream* aStream = new CompressingStream(

  new ASCII7Stream(

    new FileStream("fileName.dat")));

aStream->putString( "Hello world" );


이 클래스의 문제점에 대한 솔루션은 추상 랩퍼 인터페이스 내에 원래 오브젝트를 캡슐화하는 것입니다. 데코레이터 객체와 코어 객체는 모두 이 추상 인터페이스에서 상속됩니다. 이 인터페이스는 재귀적 구성을 사용하여 각 코어 객체에 무제한의 데코레이터 "레이어"를 추가 할 수 있습니다.


이 패턴을 사용하면 객체의 인터페이스에 대한 메소드가 아니라 객체에 책임을 추가 할 수 있습니다. 클라이언트에 제공되는 인터페이스는 연속 레이어가 지정될 때 일정하게 유지되어야합니다.


또한 핵심 오브젝트의 ID가 이제 데코레이터 오브젝트 내부에 "숨겨져"있습니다. 문제는 핵심 객체에 직접 액세스하는 것입니다.




구조

클라이언트는 항상 CoreFunctionality.doThis ()에 관심이 있습니다. 클라이언트는 OptionalOne.doThis()OptionalTwo.doThis()에 관심이 있거나 없을 수 있습니다. 이러한 각 클래스는 항상 Decorator 기본 클래스에 위임되며 해당 클래스는 항상 포함 된 "wrapper" 객체에 위임됩니다.

데코레이터 디자인 패턴 : 정의, 개념, 구조, 예시




예시

데코레이터는 객체에 동적으로 추가 책임을 부여합니다. 소나무 또는 전나무에 추가되는 장식품은 데코레이터가 바로 그 예입니다. 조명, 화환, 사탕 지팡이, 유리 장식품 등을 나무에 추가하여 축제 분위기를 연출할 수 있습니다. 장식품은 사용된 특정 장식품에 관계없이 크리스마스 트리로 인식 할 수 있는 트리 자체를 변경하지 않습니다. 추가 기능의 예로 조명을 추가하면 크리스마스 트리를 "조명화" 할 수 있습니다.


또 다른 예 : 돌격 총은 그 자체로 치명적인 무기입니다. 그러나 특정 "장식"을 적용하면 더 정확하고 조용하며 파괴적입니다.


데코레이터 디자인 패턴 : 정의, 개념, 구조, 예시




점검리스트

- 컨텍스트가 단일 코어 (또는 비선택적) 구성 요소, 여러 가지 선택적인 장식 또는 랩퍼 및 모두에게 공통적인 인터페이스인지 확인해야 합니다.

- 모든 클래스를 상호 교환 할 수 있는 "최소 공통 분모" 인터페이스를 작성해야 합니다.

- 선택적 랩퍼 클래스를 지원하기 위해 두 번째 레벨 기본 클래스 (Decorator)를 작성해야 합니다.

- Core 클래스와 Decorator 클래스는 LCD 인터페이스에서 상속됩니다.

- Decorator 클래스는 LCD 인터페이스에 컴포지션 관계를 선언하고 이 데이터 멤버는 생성자에서 초기화됩니다.

- Decorator 클래스는 LCD 객체에 위임합니다.

- 각 선택적 꾸미기에 대해 Decorator 파생 클래스를 정의하십시오.

- Decorator 파생 클래스는 래퍼 기능을 구현하고 Decorator 기본 클래스에 위임합니다.

- 클라이언트는 Core 및 Decorator 객체의 유형과 순서를 구성합니다.




주요 규칙

- 어댑터는 Subject와 다른 인터페이스를 제공합니다. 프록시는 동일한 인터페이스를 제공합니다. Decorator는 향상된 인터페이스를 제공합니다.

- 어댑터는 객체의 인터페이스를 변경하고 Decorator는 객체의 책임을 향상시킵니다. 따라서 데코레이터는 클라이언트에게 더 투명합니다. 결과적으로, Decorator는 순수한 어댑터로는 불가능한 재귀적 구성을 지원합니다.

- Composite과 Decorator는 유사한 구조 다이어그램을 가지고 있으며, 둘 다 재귀 구성에 의존하여 개방형의 객체를 구성한다는 사실을 반영합니다.

- 데코레이터는 하나의 구성 요소만 있는 Composite로 볼 수 있습니다. 그러나 데코레이터는 추가 책임을 추가합니다. 객체 집계를 위한 것이 아닙니다.

- Decorator는 서브 클래스 없이 객체에 책임을 추가 할 수 있도록 설계되었습니다. Composite의 초점은 꾸밈이 아니라 표현에 있습니다. 이러한 의도는 별개이지만 보완적입니다. 결과적으로 컴포지트 및 데코레이터는 종종 사용됩니다.

- Composite은 책임 체인을 사용하여 구성 요소가 부모를 통해 전역 속성에 액세스 할 수 있도록 합니다. 또한 Decorator를 사용하여 컴포지션의 일부에서 이러한 속성을 재정의 할 수 있습니다.

- 데코레이터와 프록시는 목적이 다르지만 구조는 비슷합니다. 둘 다 다른 객체에 대한 간접적인 수준을 제공하는 방법을 설명하고 구현은 요청을 전달하는 객체에 대한 참조를 유지합니다.

- 데코레이터를 사용하면 오브젝트의 스킨을 변경할 수 있습니다. Strategy를 사용하면 내장을 변경할 수 있습니다.

반응형