Ch3. 데코레이터 패턴 : 객체 꾸미기

OCP(Open-Closed Principle)

  • 클래스는 확장에는 열려 있어야 하지만 변경에는 닫혀 있어야 한다.

데코레이터 패턴

  • 데코레이터의 슈퍼클래스는 자신이 장식하고 있는 객체의 슈퍼클래스와 같다.

  • 한 객체를 여러 개의 데코레이터로 감쌀 수 있다.

  • 데코레이터는 자신이 감싸고 있는 객체와 같은 슈퍼클래스를 가지고 있기에 원래 객체(싸여 있는 객체)가 들어갈 자리에 데코레이터 객체를 넣어도 상관없다.

  • 데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 일 말고도 추가 작업을 수행할 수 있다.

  • 객체는 언제든지 감쌀 수 있으므로 실행 중에 필요한 데코레이터를 마음대로 적용할 수 있다.

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

Untitled

행동을 상속받으려고 Beverage의 서브클래스를 만든 게 아니라 형식으로 맞추려고 한 것

만약 상속만 서야 했다면 행동이 컴파일 시에 정적으로 결정됨. 하지만 구성을 활용하면 실행 중에 데코레이터를 마음대로 조합해서 사용할 수 있다는 장점이 있다.

→ 데코레이터를 언제든지 구현해서 새로운 행동을 추가할 수 있음.

커피 주문 시스템 코드 예제

public abstract class Beverage {
	String description = "제목 없음";

	public String getDescription() {
		return description;
	}

	public abstract double cost();
}

첨가물(condiment)를 나타내는 추상클래스(데코레이터 클래스)

public abstract class CondimentDecorator extends Beverage {
	Beverage beverage; // 각 데코레이터가 감쌀 음료를 나타내는 Beverage 객체 지정
	public abstract String getDescription();
}

음료 코드 구현

public class Espresso extends Beverage {
	public Espresso() {
		description = "에스프레소";
	}

	public double cost() {
		return 1.99.
	}
}
public class HouseBlend extends Beverage {
	public HouseBlend() {
		description = "하우스 블렌드 커피";
	}

	public double cost() {
		return .89;
	}
}

첨가물 코드 구현

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

	public String getDescription() {
		return beverage.getDescription() + "모카";
	}

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

Mocha 인스턴스에는 Beverage의 레퍼런스가 들어있다.

두가지가 필요하다

  • 감싸고자 하는 음료를 저장하는 인스턴스 변수

  • 인스턴스 변수를 감싸고자하는 객체로 설정하는 생성자(데코레이터의 생성자에 감싸고자 하는 음료 객체를 전달하는 방식을 사용)

데코레이터 적용 예시 : 자바 I/O

java.io 패키지

Last updated