반응형
디자인패턴
[Java][디자인 패턴] 10. 장식자 패턴 (Decorator Pattern)
장식자 패턴은 객체의 동적 기능을 추가하기 위해 구조를 개선하는 패턴이다.
다양한 확장을 위해 객체를 조합한다.
장식자 패턴이란?
- 장식자 패턴은 동적으로 객체를 결합하기 위해 객체지향의 구성을 통해 확장한다. (코드를 변경하지 않고 확장 가능)
- 실시간 동작으로 자신의 객체를 확장하면서, 필요로 하는 다양한 책임을 수행하고 문제를 해결해 나간다.
- 장식자의 기본 배경이 되는 개념은 복합 객체와 위임이다. 상속을 배제하고 구성을 통해 객체를 동적으로 확장한다.
장식자 패턴은 언제 사용할까?
만약 뼈대는 동일하지만 특정 기능들을 확장하거나 삭제하거나 일부만 변경하는 등 객체를 다양하게 확장하려면 어떻게 해야 할까?
이럴 경우 새로운 기능을 추가할 때 객체를 동적으로 결합해서 구성을 통해 객체를 확장할 수 있다.
장식자 패턴은 기존의 객체를 감싸서 새로운 기능을 추가하는 객체를 생성할 때 매우 유용한 패턴이다.
장식자 패턴 구성 요소
- Component (CakeComponent)
- 인터페이스를 정의한다
- ConcreateComponent (CakeConcreteComponent)
- 인터페이스에 정의 실제를 구현한다
- Decorator (CakeComponentDecorator)
- 컴포넌트를 참조하며 인터페이스를 일치화한다
- ConcreateDecorator (Strawberry, Chocolate, Mint)
- 확장 및 추가되는 기능을 작성한다.
팩토리 패턴 코드
1. CakeComponent 인터페이스
public interface CakeComponent {
String decorate();
}
2. CakeConcreteComponent 클래스
케이크의 뼈대 역할을 담당함
public class CakeConcreteComponent implements CakeComponent {
@Override
public String decorate() {
return "케이크";
}
}
3. CakeComponentDecorator
케이크를 꾸며주는 장식자들의 추상 클래스
public abstract class CakeComponentDecorator implements CakeComponent {
private final CakeComponent cakeComponent;
protected CakeComponentDecorator(CakeComponent cakeComponent) {
this.cakeComponent = cakeComponent;
}
@Override
public String decorate() {
return cakeComponent.decorate();
}
}
4. Cake ConcreteDecorator (Strawberry, Chocolate, Mint)
케이크를 꾸며주는 장식자의 구체 클래스
public class Chocolate extends CakeComponentDecorator {
public Chocolate(CakeComponent cakeComponent) {
super(cakeComponent);
}
@Override
public String decorate() {
return decorateCake() + super.decorate();
}
private String decorateCake() {
return "초코 ";
}
}
public class Mint extends CakeComponentDecorator {
public Mint(CakeComponent cakeComponent) {
super(cakeComponent);
}
@Override
public String decorate() {
return decorateCake() + super.decorate();
}
private String decorateCake() {
return "민트 ";
}
}
public class Strawberry extends CakeComponentDecorator {
public Strawberry(CakeComponent cakeComponent) {
super(cakeComponent);
}
@Override
public String decorate() {
return decorateCake() + super.decorate();
}
private String decorateCake() {
return "딸기 ";
}
}
5. 케이크 장식 테스트 코드
class CakeComponentTest {
@Test
@DisplayName("초코 케이크")
void cakeTest1() {
CakeComponent cakeComponent = new Chocolate(new CakeConcreteComponent());
assertEquals("초코 케이크", cakeComponent.decorate());
}
@Test
@DisplayName("초코 초코 딸기 케이크")
void cakeTest2() {
CakeComponent cakeComponent = new Chocolate(new Chocolate(new Strawberry(new CakeConcreteComponent())));
assertEquals("초코 초코 딸기 케이크", cakeComponent.decorate());
}
@Test
@DisplayName("민트 딸기 초코 케이크")
void cakeTest3() {
CakeComponent cakeComponent = new Mint(new Strawberry(new Chocolate(new CakeConcreteComponent())));
assertEquals("민트 딸기 초코 케이크", cakeComponent.decorate());
}
}
장식자 패턴의 장점과 단점
장점
- 상속 형태의 확장보다 더 융통성 있게 설계 가능하다.
- 객체 실행 중에도 동적으로 기능을 추가할 수 있어서 새로운 부가 기능을 추가하는 가장 효과적인 방법이다.
- 미리 클래스 등의 자원을 생성해 낭비하는 게 아니라 동적으로 처리되는 시점에 자원을 할당받아 사용 가능하다.
단점
- 작은 단위의 객체가 많이 생성된다. (단, 작은 코드로 이루어진 객체는 보다 이해하기 쉬우므로 상호 작용을 통해 다른 객체를 생성할 수 있는 원소 객체라 무조건 단점이라고 할 수 없음.)
- 유사한 성직의 작은 클래스가 증가한다. (완전 다른 클래스는 아니고 상호 작용 방법에만 차이가 있는 클래스들)
- 기존 객체를 감싸는 과정이 있어야 하므로 구성 요소를 초기화하는 작업이 필요하다.
Github 코드
참고 자료
1.쉽게 바로 써먹는 디자인 패턴 책
http://www.yes24.com/Product/Goods/93173296
반응형
'개발 > 디자인패턴' 카테고리의 다른 글
[Java][디자인 패턴] 12. 플라이웨이트 패턴 (Flyweight Patten) (0) | 2022.03.16 |
---|---|
[Java][디자인 패턴] 11. 파사드 패턴 (Facade Pattern) (0) | 2022.03.12 |
[Java][디자인 패턴] 9. 복합체 패턴 (Composite Pattern) (0) | 2022.03.08 |
[Java][디자인 패턴] 8. 브리지 패턴 (Bridge Pattern) (1) | 2022.03.07 |
[Java][디자인 패턴] 7. 어댑터 패턴 (Adapter Pattern) (0) | 2022.03.06 |