thumbnail

데코레이터 패턴이란?

데커레이터 패턴은 기본 기능에 추가 할 수 있는 기능의 종류가 많은 경우에

각 추가 기능을 Decorator 클래스로 정의 한 후 필요한 Decorator 객체를 조합함으로써 추가 기능의 조합을 설계하는 방식입니다.

예시를 통해서, 이해할 수 있습니다.

A가게에서는 인형을 팔고있습니다.

A가게에는 기본인형이 있고, 기본인형에 장식을 부착 할 수 있습니다.

기본인형에 장식이 부착된 인형은, 기본인형값 + 장식값을 받아 팔기로 하였습니다.

<br/>A가계에 인형의 가격을 계산하는 SW를 설계하고자 합니다.

현재 장식은 리본과 옷이 있습니다.

이를 설계해보면 다음과 같습니다. 일반화를 통해 다음과 같이 설계합니다.

<img alt="undefined" pathname="GZH6H4190114171803.PNG" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/GZH6H4190114171803.PNG" style="border-style:solid; border-width:1px; width:315px" title="undefined"/>

<br/>**RibbonDoll, ClothDoll 클래스는 **

Doll 클래스를 상속 받아 getPrice()를 오버라이딩 함으로써 가격정보를 갱신합니다.

public class Doll {
	public int getPrice() {
		return 5000;
	}
}
public class RibbonDoll extends Doll{
	public int getPrice() {
		return super.getPrice() + 500;
	}
}
public class ClothDoll extends Doll{
	public int getPrice() {
		return super.getPrice() + 3000;
	}
}

<br/>
<br/><span style="color:#e74c3c">하지면 여기서 몇 가지 인형이 더 추가 되었습니다.

<span style="color:#e74c3c">리본과옷인형, 신발인형, 리본신발인형, 옷신발인형 등 수 많은 인형이 추가 되었습니다.

<br/>따라서 다음과 같이 설계하였습니다.

동일하게 하위클래스에서 getPrice() 메소드를 오버라이딩 함으로써, 가격정보를 갱신하였습니다.

<img alt="undefined" pathname="S7NVPI190114163834.PNG" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/S7NVPI190114163834.PNG" style="border-style:solid; border-width:1px; width:479px" title="undefined"/>

<br/>**<span style="color:#e74c3c">하지만 또 인형이 추가되어 N개의 인형이 생겼습니다. **

<span style="color:#e74c3c">예를 들어 10개의 장식이 있다고하면 2^10 가지 조합의 인형 타입이 생길 것입니다..에고

<span style="color:#e74c3c">그럼 2^10가지의 클래스를 만들어 Doll 클래스를 상속 받을 수는 없는 노릇입니다.

<br/>데코레이터 패턴은 이 문제점을 해결해줍니다.

N개의 기능에 M개의 조합을 선택하여 사용 할 수 있는 설계를 도와줍니다.

다음은 데코레이터 패턴의 기본 구조입니다.

<img alt="undefined" pathname="TTMVOA190114171238.PNG" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/TTMVOA190114171238.PNG" style="border-style:solid; border-width:1px; width:436px" title="undefined"/>

<br/>이틀 토대로 다음과 같이 다시 설계 할 수 있습니다.

<img alt="undefined" pathname="AIIJAS190114172754.PNG" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/AIIJAS190114172754.PNG" style="border-style:solid; border-width:1px; width:408px" title="undefined"/>

<br/>
<br/>먼저 Doll 클래스는 다음과 같습니다.

public abstract class Doll {
	public abstract int getPrice();
}

<br/>BasicDoll은 Doll을 상속받으며, 기본 인형의 가격을 정의합니다.

public class BasicDoll extends Doll{
	public int getPrice() {
		return 5000;
	}
}

<br/>DollDecorator는 Doll을 상속받으며, 참조합니다.

getPrice() 메소드는 참조하는 Doll 객체에 getPrice() 메소드를 호출합니다.

public class DollDecorator extends Doll{
	private Doll doll;

	public DollDecorator(Doll doll) {
		super();
		this.doll = doll;
	}

	@Override
	public int getPrice() {
		return doll.getPrice();
	}
}

<br/>다음은 DollDecorator를 참조받는 RibbonDecorator, ClothDecorator, ShoesDecorator 클래스입니다.

public class RibbonDecorator extends DollDecorator{
	public RibbonDecorator(Doll doll) {
		super(doll);
	}

	public int getPrice() {
		return super.getPrice() + 500;
	}
}
public class ClothDecorator extends DollDecorator{
	public ClothDecorator(Doll doll) {
		super(doll);
	}

	public int getPrice() {
		return super.getPrice() + 3000;
	}
}
public class ShoesDecorator extends DollDecorator{
	public ShoesDecorator(Doll doll) {
		super(doll);
	}

	public int getPrice() {
		return super.getPrice() + 1000;
	}
}

<br/>지금의 코드로 봐서는 어떻게 동작하는지 쉽게 이해가 되지 않습니다. ? (<span style="color:#16a085">마치 재귀와 같이..)

<br/>Main 함수를 보면서 실행결과를 보면, 쉽게 이해할 수 있습니다.

	public static void main(String[] args) {
		Doll doll = new ClothDecorator(new BasicDoll());
		System.out.println(doll.getPrice());
	}
8000

ClothDecorator의 생성자 매개변수로 BasicDoll을 주입시켰습니다.

<br/>상위 클래스의 DollDecorator는 주입시킨 BasicDoll 객체를 참조 할 것입니다.

따라서 ClothDecorator의 getPrice()가 호출되면, BasicDoll의 getPrice()가 호출된 값에 + 옷의 가격을 더 해 반환 합니다.

즉 옷을 입은 인형 가격이 출력되었습니다.

<br/>그럼 다음 코드를 봅시다.

	public static void main(String[] args) {
		Doll doll = new ClothDecorator(new RibbonDecorator(new BasicDoll()));
		System.out.println(doll.getPrice());
	}
8500

이번엔 옷을 입고, 리본을 낀 인형의 가격을 출력하였습니다.

RibbonDecorator객체에는 생성자 매개변수로 BasicDoll 객체를 주입하였습니다.

ClothDecorator객체에는 생성자 매개변수로 RibbonDecorator 객체를 주입하였습니다.

<br/>ClothDecorator 객체의 getPrice() 메소드를 호출하면,

RibbonDecorator 객체의 getPrice() 메소드가 호출되고 + 옷의 가격이 더해집니다.

<br/>RibbonDecorator 객체의 getPrice() 메소드가 호출되면

BasicDoll 객체의 getPrice()가 호출되고, + 리본의 가격이 더해집니다.

<br/>따라서 BassicDoll.getPrice() + 리본의 가격 + 옷의 가격을 반환 받게 됩니다.

<br/>그럼 이 인형에 신발까지 추가 할 수 있을 것입니다.

	public static void main(String[] args) {
		Doll doll = new ClothDecorator(new RibbonDecorator(new ShoesDecorator(new BasicDoll())));
		System.out.println(doll.getPrice());
	}
9500

결과는 BassicDoll.getPrice() + 리본의 가격 + 옷의 가격 + 신발가격을 반환 받게 됩니다.

<br/>
<br/>이와 같이 데코레이터 패턴을 이용하여

3개의 장식에 대해서 다양한 조합의 장식을 부착한 인형의 가격을 알 수 있습니다.

따라서 N개의 기능에 대하여 M개의 기능을 추가한 조합의 객체 또한 정의 할 수 있을 것입니다.

<br/>
<br/>
<br/>
<br/>

CommentCount 0
이전 댓글 보기
등록
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
TOP