1. 개요

데코레이터 패턴을 사용하여 객체에 정적 또는 동적으로 추가 책임을 부여할 수 있습니다. Decorator는 원본 개체에 향상된 인터페이스를 제공합니다.

이 패턴의 구현에서 상속보다 구성을 선호하므로 각 데코레이팅 요소에 대해 계속해서 서브클래싱하는 오버헤드를 줄일 수 있습니다. 이 디자인과 관련된 재귀는 필요한 만큼 개체를 장식하는 데 사용할 수 있습니다.

2. 데코레이터 패턴 예제

크리스마스 트리 개체가 있고 그것을 장식하고 싶다고 가정합니다. 장식은 개체 자체를 변경하지 않습니다. 크리스마스 트리 외에도 화환, 틴셀, 트리 토퍼, 버블 조명 등과 같은 몇 가지 장식 항목을 추가하고 있습니다.

8포즈64T

이 시나리오에서는 원래 Gang of Four 디자인 및 명명 규칙을 따릅니다. 먼저 ChristmasTree 인터페이스와 구현을 만듭니다 .

public interface ChristmasTree {
    String decorate();
}

이 인터페이스의 구현은 다음과 같습니다.

public class ChristmasTreeImpl implements ChristmasTree {

    @Override
    public String decorate() {
        return "Christmas tree";
    }
}

이제 이 트리에 대한 추상 TreeDecorator 클래스를 만듭니다 . 이 데코레이터는 ChristmasTree 인터페이스를 구현 하고 동일한 개체를 보유합니다. 동일한 인터페이스에서 구현된 메소드는 단순히 인터페이스에서 decorate() 메소드를 호출합니다 .

public abstract class TreeDecorator implements ChristmasTree {
    private ChristmasTree tree;
    
    // standard constructors
    @Override
    public String decorate() {
        return tree.decorate();
    }
}

이제 몇 가지 장식 요소를 만듭니다. 이러한 데코레이터는 추상 TreeDecorator 클래스를 확장 하고 요구 사항에 따라 decor() 메서드를 수정합니다 .

public class BubbleLights extends TreeDecorator {

    public BubbleLights(ChristmasTree tree) {
        super(tree);
    }
    
    public String decorate() {
        return super.decorate() + decorateWithBubbleLights();
    }
    
    private String decorateWithBubbleLights() {
        return " with Bubble Lights";
    }
}

이 경우 다음이 참입니다.

@Test
public void whenDecoratorsInjectedAtRuntime_thenConfigSuccess() {
    ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());
    assertEquals(tree1.decorate(), 
      "Christmas tree with Garland");
     
    ChristmasTree tree2 = new BubbleLights(
      new Garland(new Garland(new ChristmasTreeImpl())));
    assertEquals(tree2.decorate(), 
      "Christmas tree with Garland with Garland with Bubble Lights");
}

첫 번째 tree1 개체에서는 하나의 Garland 로만 장식하고 다른 tree2 개체는 하나의 BubbleLights 와 두 개의 Garlands 로 장식합니다 . 이 패턴은 런타임에 원하는 만큼 데코레이터를 추가할 수 있는 유연성을 제공합니다.

4. 결론

이 기사에서는 데코레이터 디자인 패턴을 살펴보았습니다. 이것은 다음과 같은 경우에 좋은 선택입니다.

  • 개체의 동작 또는 상태를 추가, 향상 또는 제거하려는 경우
  • 클래스의 단일 개체의 기능을 수정하고 다른 개체는 변경하지 않으려는 경우

이 예제의 전체 소스 코드는 GitHub에서 사용할 수 있습니다 .

Generic footer banner