java 디자인 패턴 - 데코레이터(decorator) 패턴

바퀴달린 개발자·2021년 11월 15일
0

상속은 기능을 확장하는 방법을 제공한다. 하지만 다양한 조합의 기능 확장이 요구될 때 클래스가 불필요하게 증가하는 문제가 발생된다.
-> 이러한 경우에 사용할 수 있는 패턴이 데코레이터 패턴이다.

: 상속이 아닌 위임을 하는 방식으로 기능을 확장해간다.
: 동적(실시간으로 기능 변경), 책임 추가!
기능 확장을 위해 impl class를 상속받지 않고 decorator라 불리는 별도의 추상 클래스를 만들었다.

  1. 컴포넌트(interface) - 실질적인 인스턴스를 컨트롤 하는 역할
  2. concreteComponent - component의 실질적인 인스턴스 부분
  3. Decorator : Component와 concrete Decorator를 동일시 하도록 해주는 역할
  4. ConcreteDecorator : 실질적인 장식 인스턴스 및 정의, 추가된 책임의 주체 부분

컴포넌트를 구현하는 게 컨크리트컴포넌트와 데코레이터이다.

커피로 예를 들어보자,

에스프레소: 커피의 기본
아메리카노 : 에스프레소 + 물
카페라떼 : 에스프레소 + 스팀 밀크

헤이즐넛 : 아메리카노 + 헤이즐넛 시럽
카페모카 : 카페라떼 + 초콜릿
카라멜 마끼아또: 카페라떼 + 캬라멜 시럽

// Component
public class IBeberage{
	public int getTotalPrice();
}

// ContreteComponent
public class Base() implements IBeverage{
	@Override
    	public int getTotalPrice() {
    		return 0;
        }		
}

// Decorator
abstract public class AbstAdding implements IBeverage {
	
    priate IBeverage base;
    
    public AbstAdding(IBeverage base) {
    	super();
        this.base = base;
    }
    
    @Override
    public int getTotalPrice(){
    	return base.getTotalPrice();
    }
    
    protected IBeverage getBase(){
    	return base;
    }
    
// Concrete Decorator
public class Milk extends AbstAdding{
	public Milk(IBeverage material){
    	super(meterial);
    }
    
    @Ovveride
    public int getTotalPrice() {
    	return super.getTotalPrice() + 50;
    }
}

public class Espresso extends AbstAdding{
	
	public Espresso(IBeverage material){
    	super(meterial);
    }
    
    @Ovveride
    public int getTotalPrice() {
    	return super.getTotalPrice() + 150;
    }
}

//main
void main(){
	IBeverage beverage = new Base();
    beverage.getTotalPrice();
    beverage = new Espresso(beverage)'
}

데코레이터 패턴을 적용할 때 고려할점

  1. 데커레이터 대상이 되는 타입의 기능 개수에 대한 것
  2. 데코레이터 객체가 비정상적으로 동작할 때 어떻게 처리할 것인가?

참고
https://www.youtube.com/watch?v=VL9OAohbjzI

0개의 댓글