본문 바로가기
2023년 이전/디자인 패턴

디자인 패턴 - 데코레이터 패턴(Decorator Pattern)

by JeongUPark 2019. 11. 18.
반응형

데코레이터 패턴은 추가 기능이 필요 할때 서브클래스를 만들어 기능을 유연하게 확장하는 패턴을 말합니다.

 

 

Component - 기본 기능인 ConcreteComponent와 추가 기능인 Decorator의 공통 기능을 정의

ConcreteComponent - 기본 기능을 구현

Decorator - 많은 수가 존재하는 Decorator의 공통 기능 정의

ConcreteDecorator - 추가 기능 정의Decorator의 하위 클래스로 기본 기능에 추가되는 개별적인 기능을 구현. ConcreteDecorator 클래스는 ConcreteComponent 객체에 대한 참조가 필요한데, 이는 Decorator 클래스에서 Component 클래스로의 ‘합성(composition) 관계’를 통해 표현됨

 

데코레이터 패턴이 필요한 이유의 예를 한번 들어보겠습니다.

 

만일, 군인에 대한 정보를 표시할 때, 육군/해군/공군 을 나누고 사단을 나누고 병과를 나눈다고 했을때, 데코레이터 패턴을 쓰지 않았을 경우 육군 몇사단 무슨병과 해군 몇사단 무슨병과로 표현을 하게되고, 각 경우에 대하여 하나하나 전부 만들게 될것입니다. Army8DivisionCaterer(), Marine1Divisioninfantry() 이런 식으로 말이죠.

 

 

 

그래서 데코레이터 패턴을 적용하여 한번 만들어 보겠습니다.

우선 기본 Component를 만듭니다. show로 한 이유는 자신을 표현한다는 의미로 show로 정하였습니다.

public abstract class Classification {
    public abstract void show();
}

 그 다음 ConcreateComponent를 만듭니다. 여기서는 군대에 관련되어있으므로 병과는 Army/Maine/Air_Force가 됩니다.

public class BaseClassfication extends Classification {
    private String classfication;
    BaseClassfication(String classfication){
        this.classfication = classfication;
    }
    @Override
    public void show() {
        System.out.println(this.classfication);
    }
}

 그리고 추가 기능들의 공통 기능을 가질 Decorator를 만듭니다.

public class ClassificationDecorator extends Classification {
    private Classification classificationDecorator;
    ClassificationDecorator(Classification classificationDecorator){
        this.classificationDecorator = classificationDecorator;
    }

    @Override
    public void show() {
        classificationDecorator.show();
    }
}

그리고 추가 기능을 나타내는 ConcreateDecorator 들을 만듭니다. 

DivisionDecorator는 사단을 PositionDecorator는 병과를 나타냅니다.

public class DivisionDecorator extends ClassificationDecorator {
    private int division = 0;
    DivisionDecorator(Classification classification, int division) {
        super(classification);
        this.division = division;
    }

    @Override
    public void show() {
        super.show();
        showDivision();
    }

    private void showDivision() {
        System.out.println("\t"+division+" divisions");
    }
}
public class PositionDecorator extends ClassificationDecorator {
    private String position;
    PositionDecorator(ClassificationDecorator decoratedDisplay, String position) {
        super(decoratedDisplay);
        this.position = position;
    }

    @Override
    public void show() {
        super.show();
        showposition();
    }
    private void showposition(){
        System.out.println("\t" +position+" position");
    }
}

 그런 후 다음과 같이 실행합니다.

public class Client {
    public static void main(String[] args){

        BaseClassfication soldier_1 = new BaseClassfication("Army");
        Classification c = new PositionDecorator(new DivisionDecorator(soldier_1,8),"artilleryman");
        c.show();

        BaseClassfication soldier_2 = new BaseClassfication("Marine");
        Classification c_2 = new DivisionDecorator(soldier_2,1);
        c_2 = new PositionDecorator(c_2,"infantry");
        c_2.show();

    }
}

이렇게 실행을 하면 그 결과는

Army
	8 divisions
	artilleryman position
Marine
	1 divisions
	infantry position

 이렇게 나옵니다.

 

위처럼 데코레이터 패턴을 사용하면 class에 하나하나 기능을 추가하거나 확장할 필요 없이 서브클래스를 통하여 추가 기능을 확장하여 사용할 수 있습니다.

 

 

참고

https://jusungpark.tistory.com/9?category=630296

https://gmlwjd9405.github.io/2018/07/09/decorator-pattern.html

https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0_%ED%8C%A8%ED%84%B4

 

반응형