디자인 패턴 톺아보기 - Decorator Pattern

Updated:

1. 데코레이터 패턴(Decorator Pattern) 이란?

GOF 에서 말하는 데코레이터 패턴의 목적은 아래와 같습니다.

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

객체에 동적으로 새로운 책임을 추가할 수 있게 합니다. 기능을 추가하려면, 서브 클래스를 생성하는 것보다 융통성 있는 방법을 제공합니다.

1.1. 구조

Sample / Sequence Diagram

image

  • Component
    • 동적으로 추가할 서비스를 가질 가능성이 있는 객체들에 대한 인터페이스
  • ConcreteComponent
    • 추가적인 서비스가 실제로 정의되어야 할 필요가 있는 객체
  • Decorator
    • Component 객체에 대한 참조자를 관리하면서 Component에 정의된 인터페이스를 만족하도록 인터페이스를 정의
  • ConcreteDecorator
    • Component에 새롭게 추가할 서비스를 실제로 구현하는 클래스

1.2. 사용 방법

  1. Decorator는 자신의 Component 객체 쪽으로 요청을 전달합니다. 요청 전달전 및 전달 후에 자신만의 추가 연산을 선택적으로 수행할 수도 있습니다.

1.3. 장/단점

  • Consider the left design (problem):
    • Extending functionality at compile-time.
    • Explosion of subclasses.
  • Consider the right design (solution):
    • Extending functionality at run-time.
    • Recursively nested decorators.

1.4. 고려사항

  • Advantages (+)
    • Provides a flexible alternative to subclassing.
    • Allows an open-ended number of added functionalities.
    • Simplifies classes.
  • Disadvantages (–)
    • Provides no reliability on object identity.

2. 데코레이터 패턴(Decorator Pattern) 사용예시

데코레이터 패턴은 다음 경우에 사용합니다.

  • 다른 객체에 영향을 주지 않고 개개의 객체에 새로운 책임을 추가하기 위해 사용합니다.
  • 제거될 수 있는 책임에 대해 사용합니다.
  • 실제 상속으로 서브 클래스를 계속 만드는 방법이 실질적이지 못할 때 사용합니다. 너무 많은 수의 독립된 확장이 가능할 때 모든 조합을 지원하기 위해 이를 상속하고 해결하면 클래스 수가 폭발적으로 많아지게 됩니다. 아니면 클래스 정의가 숨겨지든가, 그렇지 않더라도 서브클래싱을 할 수 없게 됩니다.

2.1. GOF 패턴

2.1.1. Component

abstract class Component { 
	 public abstract String operation();    
}

2.1.2. ConcreteComponent

class Component1 extends Component {
	public String operation() {
		return "Hello World From Component1";
	}
}

2.1.3. Decorator

abstract class Decorator extends Component {
	Component component;
	public Decorator(Component component) {
		this.component = component;
	}
	
	public String operation() {
		return component.operation();
	}
}

2.1.4. ConcreteDecorator

class Decorator1 extends Decorator {
	public Decorator1(Component component) {
		super(component);
	}
	
	public String operation() {
		String result = super.operation();
		return addBehavior(result);
	}
	
	private String addBehavior(String result) {
		return "***" + result + "***";
	}
}

class Decorator2 extends Decorator {
	public Decorator2(Component component) {
		super(component);
	}
	
	public String operation() {
		String result = super.operation();
		return addBehavior(result);
	}
	
	private String addBehavior(String result) {
		return "===" + result + "===";
	}
}

2.1.5. Main

public class Main{
	public static void main(String[] args) {
		Component component = new Component1();
		System.out.println("(1) " + component.operation());
		
		component = new Decorator1(new Decorator2(component));
		System.out.println("(2) " + component.operation());
	}
}

결과는 아래와 같습니다.

(1) Hello World From Component1
(2) ***===Hello World From Component1===***

참고 자료

Leave a comment