본문 바로가기
OOP/<헤드 퍼스트 디자인 패턴>, 에릭 프리먼 외

Decorator

by 민휘 2023. 2. 24.

핵심 의도

데코레이터 패턴으로 객체에 추가 요소를 실행 중에 동적으로 더할 수 있다. 데코레이터를 사용하면 서브클래스를 만들 때보다 훨씬 유연하게 기능을 확장할 수 있다.

 

적용 상황

감싸고 있는 객체에 행동을 추가하거나 위임하는 용도로 만들어진다. 예를 들어 문자열을 다양한 방법으로 출력하고 싶을 때 사용할 수 있다. 문장 앞에 줄번호를 붙이거나, 소문자로 바꾸어 출력하거나, 박스로 감싸서 출력할 수 있다. 이때 문자열은 감싸지는 객체이고 추가하는 행동은 데코레이터의 책임이다.

 

솔루션의 구조와 각 요소의 역할

객체에게 책임을 분할하기

어떤 객체와 상호작용하는 다른 객체들은 그 객체의 장식의 유무와 상관없이 그 객체에게 메시지를 보낸다. 데코레이터에게도 원래 객체와 동일한 메시지 요청이 오므로, 이 메시지를 수신하려면 데코레이터와 감싸지는 객체는 같은 타입이어야 한다.

감싸지는 객체의 책임은 ConcreateComponent에, 장식의 책임은 Decorator에 할당한다. 이 둘은 같은 타입이어야 하므로 Component를 구현하거나 상속한다. 장식 기능의 구체적인 구현은 ConcreteDecorator에서 담당한다.

구현 포인트

데코레이터 패턴은 OCP 규칙을 효과적으로 지킬 수 있는 패턴이다. OCP는 기존 코드를 변경하지 않고 확장으로 새로운 행동을 추가하는 기법이다. 요구사항이 변경이 발생하는 상황에서 유연하게 코드를 관리할 수 있다.

적용 예시

요구사항

커피의 주문 시스템 구축하기. 현재 커피의 종류는 HouseBlend, DarkRoast, Decaf, Espresso가 있고 추가할 수 있는 메뉴는 Milk, Soy, Mocha, Whip가 있다.

설계

Beverage (감싸지는 객체와 데코레이터의 추상 클래스)

public abstract class Beverage {
	String description = "Unknown Beverage";
  
	public String getDescription() {
		return description;
	}
 
	public abstract double cost();
}

CondimentDecorator (데코레이터 추상 클래스)

public abstract class CondimentDecorator extends Beverage {
	Beverage beverage;
	public abstract String getDescription();
}

DarkRoast (감싸지는 객체)

public class DarkRoast extends Beverage {
	public DarkRoast() {
		description = "Dark Roast Coffee";
	}
 
	public double cost() {
		return .99;
	}
}

Milk (데코레이터 객체)

public class Milk extends CondimentDecorator {
	public Milk(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Milk";
	}

	public double cost() {
		return .10 + beverage.cost();
	}
}

Entry Point

public static void main(String args[]) {
	Beverage beverage = new Espresso();
	System.out.println(beverage.getDescription() 
			+ " $" + beverage.cost());
 
	Beverage beverage2 = new DarkRoast();
	beverage2 = new Mocha(beverage2);
	beverage2 = new Mocha(beverage2);
	beverage2 = new Whip(beverage2);
	System.out.println(beverage2.getDescription() 
			+ " $" + beverage2.cost());
 
	Beverage beverage3 = new HouseBlend();
	beverage3 = new Soy(beverage3);
	beverage3 = new Mocha(beverage3);
	beverage3 = new Whip(beverage3);
	System.out.println(beverage3.getDescription() 
			+ " $" + beverage3.cost());
}

 

데코레이터 패턴을 적용한 객체와 데코레이터들은 외부에서 받은 메시지 요청을 내부에서 연쇄적으로 처리한다.

'OOP > <헤드 퍼스트 디자인 패턴>, 에릭 프리먼 외' 카테고리의 다른 글

Singleton  (0) 2023.02.24
Simple Factory, Factory Method, Abstract Factory  (0) 2023.02.24
Observer  (0) 2023.02.24
Strategy  (0) 2023.02.24
공부 방법 설정  (0) 2023.02.24