[Java] 데코레이터 패턴

charco·2021년 7월 27일
0

나도TIL

목록 보기
12/55

데코레이터 패턴을 이용하면 어떤 오브젝트에 정적으로 또는 동적으로
책임(기능)을 추가할 수 있다. -Baeldung-

참고한 링크: https://www.baeldung.com/java-decorator-pattern

데코레이터 패턴

데코레이터 패턴은 말 그대로 어떤 오브젝트에 대해 데코레이션 하듯이
기능을 추가해주는 것이다.

A라는 인터페이스가 있고 B, C 라는 구현체가 있다면
B가 핵심 기능을 담당하고 C가 부가 기능을 담당한다.
C는 B를 주입받아 B에게 핵심 기능을 위임하고
자신은 부가 기능에 대해 처리한다.

말이 어려우니 그림으로 보자.

예를 들어 A 가 DAO인터페이스이고 B가 데이터베이스의 CRUD 에 대한 책임을 갖고 있다면 C는 트랜잭션에 대한 책임만 담당할 수 있다.
C 는 자신의 트랜잭션 메서드들 사이에 B 의 메서드를 호출하며 두개의 책임을 하나로 묶을 수 있다.

구현해보기

Baeldung이 제공하는 예제를 이용해보자.

아까 그림보다 조금더 복잡하긴 한데, 부가기능을 담는 클래스에 구현체가 여러개 생겼을 뿐이다.
ChristmasTreeImpl 의 decorate() 이 핵심 기능이고
TreeDecorator 의 구현체들의 메서드가 부가 기능이다.
꾸미자 방울로, 꾸미자 꽃으로 이런식으로 부가 기능을 적용할 것이다.

ChrismasTree interface

public interface ChristmasTree {
    //인터페이스이기 때문에 public abstract 생략
    void decorate();
}

ChristmasTreeImpl class

//핵심 기능을 담당하는 클래스
public class ChristmasTreeImpl implements ChristmasTree {
    @Override
    public void decorate() {
        System.out.println("꾸미자 ");
    }
}

TreeDecorator class

//부가 기능을 담는 클래스
public class TreeDecorator implements ChristmasTree{
    //핵심 기능을 담는 오브젝트를 주입받는다.
    private ChristmasTree tree;

    public TreeDecorator(ChristmasTree tree) {
        this.tree = tree;
    }

    @Override
    public void decorate() {
        tree.decorate();
    }
}

Garland class

public class Garland extends TreeDecorator{
    public Garland(ChristmasTree tree) {
        super(tree);
    }

    @Override
    public void decorate() {
        super.decorate();
        decorateWithTreeDecorator();
    }

    private void decorateWithTreeDecorator(){
        System.out.println("꽃잎으로");
    }
    
}

구현 클래스 나머지 3개는 거의 같다.

테스트

//테스트 클래스(클라이언트)
public class DecoratorTest {

    @Test
    public void decoratorPatternTest(){
        // 부가기능 오브젝트에 핵심 기능 오브젝트를 주입해준다.
        //런타임시 동적으로 오브젝트의 관계가 형성돼 부가기능이 적용된다.
        ChristmasTree christmasTree = new Garland(new ChristmasTreeImpl());

        christmasTree.decorate();
        //결과:
        //꾸미자
        //꽃잎으로

        ChristmasTree christmasTree1 = new TreeTopper(new ChristmasTreeImpl());

        christmasTree1.decorate();
        //결과:
        //꾸미자
        //트리 꼭대기 장식으로
    }
}

마무리

  • 장점 : 모듈의 책임(기능)을 분리하여 깔끔한 코드가 된다.
  • 단점 : 부가기능과 핵심기능을 결합하기 위해 어디선가 관계를 지정해줘야 한다. 위의 코드에서는 클라이언트가 그 책임을 맡고있다.

데코레이터 패턴은 Spring AOP를 이해하려면 알아야 한다. 확실히 알고 넘어가는게 좋을 것 같다.

profile
아직 배우는 중입니다

0개의 댓글