본문 바로가기

객체지향

[디자인 패턴] Decorator Pattern

반응형

개념: 객체의 추가적인 요건을 동적으로 추가하는 패턴

Decorator는 글자 그대로 장식가로서, 중심이 되는 객체가 반환하는 값에 추가적으로 더해져서 결과값 반환

 

ex)스타벅스커피의 경우 커스터마이징 음료 가능

 

구성

component(interface,abstract) 기능정의

concreatecomponent: 컴포넌트 책임기능 실제화

Decorator: 컴포넌트의 실제화보단, componet와 동일시 하도록, decorator가 즉 componet 

concreteDecorate: 추가된 책임 기능 구현을 위한 클래스, 

 

왜 사용해야하나?

 

하나의 객체의 부가적인 기능을 덧붙여야할때

동일한 객체를 여러개만들어야하지만, 각각의 다른 기능을 첨가할 필요가 있을때 ,

많은 객체에 다양한 부가기능을 쉽고 빠르게 적용 가능

 

장점

중심이 되는 객체를 수정하지 않고 동적으로 추가 또는 삭제 할 수있다.

객체지향의 원칙 OCP에 충실한 패턴

-클래스는 확장에 대해서 열려있어햐 하지만, 코드변경에 대해서 닫혀있어야 한다.

-기존객체가 수정되거나, 데코레이터가 수정되더라도, 해당클래스의 내용만 변경해주면 되기때문에 

변경에대해서 닫혀있다.

 

단점

클래스가 많이 추가되는 경우 남들이 봤을때 이해하기 힘든 디자인

코드복잡해진다

 

 

번외

-상속과 데코레이터 패턴의 차이는 무엇일까

상속은 하위클래스를 생성하는 방법으로 확장

데코레이터패턴은 기본객체에 추가되는 객체를 생성하는 방법으로 확장

상속은 오버라이딩을 통해 기능을 전부명시

데코레이터패턴은 기본기능은 놔드고, 추가되는 기능만 명시해줄수있다.

 

composite패턴과 비슷

데코레이터패턴은 한 구성 요소만을 갖는 composite패턴이라고볼수있다.

그러나 목적에서 차이가 있다.

composite패턴은 목적이 생성되어있는 객체들간의 합성

데코레이터패턴은 목적이 객체에 새로운 행동을 추가하는데 있음

 

 

 

 

import java.util.Scanner;


public class Main {
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        IBeverage iBeverage=new Base();
        boolean done=false;
        while(!done){
            System.out.println("선택:1번 샷추가/2번 우유추가");
            switch(sc.nextInt()){
                case 0:
                    done=true;
                break;
                case 1:
                    iBeverage=new Espresso(iBeverage);
                    break;
                case 2:
                    iBeverage=new Milk(iBeverage);
                    break;
            }
            System.out.println("욤료현재가격"+iBeverage.getTotalPrice());
        }
    }
}

 

 

public interface IBeverage {
int getTotalPrice();
}
public class Base implements IBeverage{
    @Override
    public int getTotalPrice() {
        return 0;
    }
}
abstract public class AbstAdding implements IBeverage{
    private IBeverage base;
    public AbstAdding(IBeverage base){
        super();
        this.base=base;
    }
    @Override
    public int getTotalPrice() {
        return base.getTotalPrice();
    }
    public IBeverage getBase(){
     return base;
    }

}
public class Espresso extends AbstAdding{

    static protected int espressocnt=0;

    public Espresso(IBeverage base) {
        super(base);
    }

    @Override
    public int getTotalPrice() {
        return super.getTotalPrice()+getAddprice();
    }

    private int getAddprice() {
        espressocnt+=1;
        int addPrice=100;
        if(espressocnt>1){
            addPrice=70;
        }
        return addPrice;
    }
}
public class Milk extends AbstAdding {
    public Milk(IBeverage base) {
        super(base);
    }

    @Override
    public int getTotalPrice() {
        return super.getTotalPrice()+50;
    }
}

https://scorpio-mercury.tistory.com/19

반응형