컴포지트패턴 (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.

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

 

오늘 살펴볼  Composite 패턴은 Structural 패턴에 속한다.  

 

Composite Pattern Structure

 

A typical Composite object structure might look like this:



패턴의 목적 ( Intent ) : 

 

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

컴 포지트 패턴은 객체들의 관계를 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴으로, 사용자가 단일 객체와 복합 객체 모두 동일하게 다루도록 하는 패턴이다. 따라서, {객체의 그룹}과 {하나의 객체}가 동일한 행위를 할 때 적용되야 하며, 또한 트리구조를 생성할 때 사용될 수 있다. 

 

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


그 래픽 툴은 사용자들로 하여금 간단한 컴포넌트 ( ex. 선, 사각형, 문자, 그림 등등 )부터 복잡한 컴포넌트 ( ex. 글씨가 들어간 사각형 )에 이르기까지 간단하게 표현할 수 있도록 해준다. 이를 간단히 구현하자면 각각의 클래스를 정의하는 것이다. Line클래스, Rectangle 클래스를 각각 정의해서 가져다가 쓰면 되는데 단순히 이렇게 구현을 하면 나중에 큰 문제가 발생 할 수 있다. 왜냐하면 프리미티브 객체와 컨테이너 객체를 다르게 다루어야 하기 때문이다. 이게 무슨 소리냐 하면, 그림판에서 하나의 직선을 그었다고 하자. 이 직선은 시작점과 끝점 좌표를 가지고 있는 하나의 객체겠지? 그런데 또다른 직선을 그었다. 두번째 직선 역시 시작점과 끝점 좌표를 가지고 있겠지. 그런데 이 두개를 한꺼번에 저장하려면 두개의 직선 객체를 가지고있는 또다른 wrapper 클래스가 있어야 할 것이다. 그런데 직선이 몇개가 될지 누가 아냐? 그리는 사람이 몇개를 그릴지는 아무도 모르잖아? 그래서 이런 식으로 접근하다가는 평생해도 제대로된 그래픽 툴을 못 만들 것이다. 그래서 나온 것이 바로 이 컴포지트 패턴인 것이다. 아래 다이어그램을 보자.


 

위 다이어그램은 직선, 사각형, 문자, 그림을 모두 그래픽 객체를 구현하는 클래스로 만들어 버리고 각 그래픽 클래스는 자식으로 그래픽 클래스를 가질 수 있도록 했다. 그래픽 클래스가 그래픽 클래스를 자식으로 갖는다? 이해가 되는가? 예를 들어보자.

내 가 어제 하나의 그림을 그렸다. 이 그림은 사각형과 직선 그리고 문자를 가지고 있다. 그리고 오늘 나는 두번째 그림을 그리면서 어제 그린 그림과 또 다른 선, 사각형을 그려넣었다. 이것을 다이어그램으로 표현한 것이 아래 그림이다.

aPicture, aTest, aLine, aRectangle은 모두 그래픽 객체이다. 이 그래픽 객체들은 또 다른 그래픽 객체들을 자식으로 가지고 있다. 이제 이해가 되는가?


유용성 ( Applicability ) :

 Use the Composite pattern when
· you want to represent part-whole hierarchies of objects.
· you want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.



등장 인물 ( Participants ) :

· Component (Graphic)
o declares the interface for objects in the composition.
o implements default behavior for the interface common to all classes, as appropriate.
o declares an interface for accessing and managing its child components.
o (optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate.
· Leaf (Rectangle, Line, Text, etc.)
o represents leaf objects in the composition. A leaf has no children.
o defines behavior for primitive objects in the composition.
· Composite (Picture) 

o defines behavior for components having children.
o stores child components.
o implements child-related operations in the Component interface.
· Client
o manipulates objects in the composition through the Component interface.

 


원리 ( Collaborations ) :

· Clients use the Component class interface to interact with objects in the composite structure. If the recipient is a Leaf, then the request is handled directly. If the recipient is a Composite, then it usually forwards requests to its child components, possibly performing additional operations before and/or after forwarding.


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

The Composite pattern


· defines class hierarchies consisting of primitive objects and composite objects. Primitive objects can be composed into more complex objects, which in turn can be composed, and so on recursively. Wherever client code expects a primitive object, it can also take a composite object.  

· makes the client simple. Clients can treat composite structures and individual objects uniformly. Clients normally don't know (and shouldn't care) whether they're dealing with a leaf or a composite component. This simplifies client code, because it avoids having to write tag-and-case-statement-style functions over the classes that define the composition.
· makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code. Clients don't have to be changed for new Component classes.
· can make your design overly general. The disadvantage of making it easy to add new components is that it makes it harder to restrict the components of a composite. Sometimes you want a composite to have only certain components. With Composite, you can't rely on the type system to enforce those constraints for you. You'll have to use run-time checks instead.

 

관련 패턴들 : 

 Often the component-parent link is used for a Chain of Responsibility.
Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild.
Flyweight lets you share components, but they can no longer refer to their parents.
Iterator can be used to traverse composites.
Visitor localizes operations and behavior that would otherwise be distributed across Composite and Leaf classes.

 

추가 정보 :

  • Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.
  • Composite can be traversed with Iterator. Visitor can apply an operation over a Composite. 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. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes.
  • Composite can let you compose a Mediator out of smaller pieces through recursive composition.
  • 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.
  • Flyweight is often combined with Composite to implement shared leaf nodes.

 

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

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

http://www.journaldev.com/1535/composite-design-pattern-in-java-example-tutorial