데코레이터패턴 (1)

Creational Patterns ( 생성 패턴 )

These design patterns provides way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case. 

생성패턴은 객체의 생성로직을 숨기고 new 명령어를 통하지 않고 객체를 생성하는 방법들을 제공한다. 이는 특정 상황에서 어떤 방법으로 객체를 생성해야할지를 결정하는데 있어서 유연성을 제공한다. 


 Structural Patterns ( 구조적 패턴 )

These design patterns concern class and object composition. Concept of inheritance is used to compose interfaces and define ways to compose objects to obtain new functionalities. 

구조적 패턴들은 클래스와 객체의 구성에 관여한다.

 

 Behavioral Patterns ( 행위적 패턴 )

These design patterns are specifically concerned with communication between objects.

이 패턴들은 객체들 사이의 커뮤니케이션에 관심을 가진다.

 

오늘 살펴볼  Decorator 패턴은 Structural 패턴에 속한다.  이 패턴은 컴포지트 패턴과 비슷한 다이어그램을 가지고 있다. 

 

Decorator Pattern Structure


패턴의 목적 ( Intent ) : 

 Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

 동적으로 객체에 책임(꾸밈)을 추가한다. 데코레이터는 기능을 확장하기 위한 subclassing이 아닌 다른 유동적인 방법을 제공한다. 


패턴이 나오게 된 동기 ( Motivation ) :

일반적으로 간단한 프로젝트가 아닌 이상 하나의 클래스 내에서 모든 것을 해결하는 일은 거의 없다. 유지보수를 위해서라도 기능별로 클래스를 나누게 되는데 데코레이터 패턴도 이런 식의 생각에서 나오게 된 것이다. 그래서 상속을 사용하게 되기도 하는데 이는 매우 기본적인 방법이며 flexible하지 않고 정적이다. 따라서 동적으로 기능확장이 용이하도록 한 것이 바로 이 데코레이터 패턴이다. 아래 그림은 TextView에 ScrollDecorator와 BorderDecorator를 이용하여 책임(꾸밈)을 추가한 결과이다.

 

유용성 ( Applicability ) :

Use Decorator

데코레이터 패턴은 아래와 같은 상황에서 유용하다.


· to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects.

다른 객체에 영향을 주지 않고 동적으로 투명하게 독립적인 객체들을 추가할 때
· for responsibilities that can be withdrawn.

철회가 가능한 책임(꾸밈)을 추가하고 싶을 때
· when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing. 

서브클래싱으로 기능확장하는 것이 비실용적일 때


등장 인물 ( Participants ) :

· Component (VisualComponent)
o defines the interface for objects that can have responsibilities added to them dynamically.

동적으로 추가되는 책임을 가질 수 있는 객체를 위한 인터페이스를 정의한다.
· ConcreteComponent (TextView)
o defines an object to which additional responsibilities can be attached.

추가적인 책임을 가질 수 있는 객체를 정의한다.
· Decorator
o maintains a reference to a Component object and defines an interface that conforms to Component's interface.

이 패턴의 메인이다. 컴포넌트 객체의 레퍼런스를 가지고 있으며, 컴포넌트와 조화를 이루는 인터페이스를 정의한다.
· ConcreteDecorator (BorderDecorator, ScrollDecorator)
o adds responsibilities to the component.

컴포넌트에 책임을 부과한다. 


원리 ( Collaborations ) :

· Decorator forwards requests to its Component object. It may optionally perform additional operations before and after forwarding the request.


패턴 사용의 장단점 ( Consequences ): 

The Decorator pattern has at least two key benefits and two liabilities:

 

1. More flexibility than static inheritance. 정적인 상속보다 훨씬 유동적이다. The Decorator pattern provides a more flexible way to add responsibilities to objects than can be had with static (multiple) inheritance. With decorators, responsibilities can be added and removed at run-time simply by attaching and detaching them. In contrast, inheritance requires creating a new class for each additional responsibility (e.g., BorderedScrollableTextView, BorderedTextView). This gives rise to many classes and increases the complexity of a system.
Furthermore, providing different Decorator classes for a specific Component class lets you mix and match responsibilities.
Decorators also make it easy to add a property twice. For example, to give a TextView a double border, simply attach two BorderDecorators. Inheriting from a Border class twice is error-prone at best.


2. Avoids feature-laden classes high up in the hierarchy. Decorator offers a pay-as-you-go approach to adding responsibilities. Instead of trying to support all foreseeable features in a complex, customizable class, you can define a simple class and add functionality incrementally with Decorator objects. Functionality can be composed from simple pieces. As a result, an application needn't pay for features it doesn't use. It's also easy to define new kinds of Decorators independently from the classes of objects
they extend, even for unforeseen extensions. Extending a complex class tends to expose details unrelated to the responsibilities you're adding.


3. A decorator and its component aren't identical. A decorator acts as a transparent enclosure. But from an object identity point of view, a decorated component is not identical to the component itself. Hence you shouldn't rely on object identity when you use decorators.


4. Lots of little objects. A design that uses Decorator often results in systems composed of lots of little objects that all look alike. The objects differ only in the way they are interconnected, not in their class or in the value of their variables. Although these systems are easy to customize by those who understand them, they can be hard to learn and debug. 

 

관련 패턴들 : 

Adapter : A decorator is different from an adapter in that a decorator only changes an object's responsibilities, not its interface; an adapter will give an object a completely new interface. 

 Composite : A decorator can be viewed as a degenerate composite with only one component. However, a decorator adds additional responsibilities—it isn't intended for object aggregation.
Strategy : A decorator lets you change the skin of an object; a strategy lets you change the guts. These are two alternative ways of changing an object.


추가 정보 :  

  • Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.
  • Adapter changes an object's interface, Decorator enhances an object's responsibilities. Decorator is thus more transparent to the client. As a consequence, Decorator supports recursive composition, which isn't possible with pure Adapters.
  • Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.
  • A Decorator can be viewed as a degenerate Composite with only one component. However, a Decorator adds additional responsibilities - it isn't intended for object aggregation.
  • Decorator is designed to let you add responsibilities to objects without subclassing. Composite's focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.
  • Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition.
  • Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests.
  • Decorator lets you change the skin of an object. Strategy lets you change the guts.
  • Decorator pattern is helpful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the number of choices are more.
  • The disadvantage of decorator pattern is that it uses a lot of similar kind of objects (decorators).
    데코레이터 패턴의 단점은 유사한 데코레이터 객체가 많아질 수 있다는 점이다.
  • Decorator pattern is used a lot in Java IO classes, such as FileReader, BufferedReader etc.
    데코레이터 패턴은 FileReader나 BufferedReader와 같은 Java IO 클래스들에서 많이 사용되고 있다.

 

출처 :  http://sourcemaking.com/design_patterns/decorator

Design Patterns : Element of Reusable Object Oriented Software ( by GoF, 1994 )  

http://www.journaldev.com/1540/decorator-pattern-in-java-example-tutorial

 

 

 

실생활을 예로 든 좋은 예제는 아래에서 확인하기 바란다.

http://warmz.tistory.com/757