본문 바로가기

Development/Spring Framework

스프링디자인패턴(3) 데코레이터 패턴 - Decorator Pattern


 

데코레이터 패턴 [ Decorator Pattern ]

 

Decorator는 장식자라고 보면 됩니다. 이는 해석 그대로 원본에 장식을 더하는 패턴입니다. 이는 Proxy 패턴과 구현 방법은 동일하지만, 반환 값에 장식을 입힌다는 것에 차이를 갖고 있습니다. 즉, 데코레이터 패턴을 통해 추가적 요건을 동적으로 추가하는 것입니다.

 

둘의 차이를 한 번 더 정리하자면 아래 표와 같습니다.

 

 

 

데코레이터 패턴 UML

 

 

  • 위 그림은 데코레이터 패턴의 기본 UML입니다.

 

데코레이터 패턴 특징

 

  • 가장 큰 특징은 메서드 호출 반환 값에 변화를 주기 위해 중간에 장식자를 두는 패턴입니다.

  • 확장에는 열려있고, 변경에는 폐쇄적이라는 점에서 OCP 원칙과 추상화된 인터페이스에 의존한다는 점에서 DIP 원칙이 적용되어야 합니다. 즉, 디자인 원칙은 기존 코드는 변경하지 않고, 확장으로 간단한 행동 추가가 가능하도록 설계하는 것입니다.

  • Concrete Decorator는 인터페이스를 상속 받아 Real Subject와 같은 이름의 메서드를 구현합니다.
  • Decorator는 Concrete Decorator에 대한 참조 변수를 가지며, 인터페이스 타입으로 Concrete Decorator 인스턴스를 생성합니다.

  • Concrete Decorator와 같은 이름을 가진 메서드를 호출하고, 반환 값에 장식을 더해 클라이언트에 반환합니다.

  • Concrete Decorator의 메서드를 호출 전/후 별도의 로직 수행이 가능합니다.

 

데코레이터 패턴 적용 예시

 

배고픈 주하 커플은 피자스쿨에서 피자를 시켜먹으려고 한다.
메뉴를 보니 토핑을 추가할수도 있고, 토핑 없이 메뉴를 주문할 수 있다.

이를 코드로 구현한다고 하였을 때, 모든 토핑과 토핑이 적용된 피자와 미적용된 피자마다 클래스를 생성한다면 생산성도 떨어질뿐더러 메모리 문제가 발생할 수 있습다. 그래서 아래와 같이 적용해보고자 합니다.

 

1.  Pizza 추상 클래스

 

가장 상위의 추상 클래스로 토핑을 적용하지 않은 순수한 형태의 피자입니다. 피자스쿨은 기본이 되는 해당 클래스를 기반으로 페퍼로니 피자를 만들수도 있고, 페퍼로니 피자를 만들수도 있습니다.

 

 

2.  CondimentDecorator

 

Pizza 클래스를 상속 받은 토핑의 추상화 클래스입니다. 이 친구 덕분에 토핑이 추가된 경우 메뉴의 이름을 변경해줄수 있습니다!

예를 들어..

일반 치즈피자가 아니라, 치즈피자에 올리브를 토핑한 경우 반환 값을 "올리브 치즈피자"로 해줄 수 있는 친구인 것이지요.

 

 

3.  Pizza 클래스 구현

 

 

4. 토핑

 

 

이렇게 피자에 토핑별로 추가하고, 가격이나 메뉴 이름에 이름을 꾸며주는 일을 해주는 것이 ' 데코레이터 패턴 ' 입니다.

이제 한 번 주문을 받아보겠습니다.

 

 

 

결과

 

 

 

자바에서의 데코레이터 패턴

 

주로 I/O 클래스가 데코레이터 패턴을 활용해 구현되고 있다고 합니다. 해당 내용은 좀 더 학습한 뒤에 추가하도록 하겠습니다.