헤드 퍼스트 디자인 패턴 - 3장 데코레이터 패턴 in Swift

koi·2022년 10월 2일
1
post-thumbnail

📖 3장 - 데코레이터 패턴

☕️ 스타버즈 주문 시스템을 만들어보자

이번에는 스타버즈 커피샵(스타벅스..?)에서 다양한 음료들을 모두 포괄하는 주문 시스템을 만드려 합니다.

기존의 스타버즈 주문 시스템

기존의 시스템을 상속을 이용해서 바꿔봅시다.


스타버즈 주문 시스템 상속으로 개선하기

옵션 선택사항을 슈퍼클래스 Beverage에 포함시키고, 음료를 서브클래스로 구현합니다.


하지만 이렇게 구현할 경우

  • 추가적인 옵션이나 메뉴가 생겼을 경우 슈퍼클래스를 수정해야함
  • 클래스가 어마어마하게 많아지거나
  • 일부 서브클래스에는 적합하지 않은 기능을 베이스 클래스에 추가하게 되는 문제가 생김
    → 서브클래스를 만드는 방식은 컴파일시 행동이 결정되므로 서브클래스가 사용하지 않는 행동도 상속받게 됨

효율적이지 못할 뿐더러 디자인 원칙 중 하나인 개방 폐쇄 원칙에 어긋나게 됩니다.

디자인 원칙
OCP (Open-Closed Principle)
클래스는 확장에 대해서는 열려 있어여 하지만 코드 변경에 대해서는 닫혀 있어야 한다.

상속을 써서 음료 가격과 첨가물(샷, 시럽, 우유, 휘핑 크림 등) 가격을 합한 총 가격을 계산하는 방법은 그리 좋은 방법이 되지 못했습니다.


그래서 우리가 대신 사용할 방법은 다음과 같습니다.
특정 음료에서 시작해서 첨가물로 음료를 장식하는(Decorate) 방법 입니다.

데코레이터를 써서 음료 주문을 완성하는 법

  1. DarkRoasat 객체에서 시작합니다.
  2. 손님이 모카를 주문했으니 Mocha 객체를 만들고 그 객체로 DarkRoast를 감쌉니다.
  3. 손님이 휘핑 크림도 같이 주문했기 때문에 Whip 데코레이터를 만들고 그 객채로Mocha를 감쌉니다.
  4. 마지막으로 가격을 구할 때는 가장 바깥쪽에 있는 데코레이터인 Whipcost()를 호출하면 됩니다. 그러면 Whip에서는 그 객체가 장식하고 있는 객체에게 가격 계산을 위임합니다. 가격이 구해지고 나면 구해진 가격에 휘핑크림의 가격을 더한 다음 그 결과를 리턴합니다.

데코레이터 패턴이란?

데코레이터 패턴에서는 객체의 추가적인 요건을 동적으로 첨가합니다.
데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공합니다.

  • 데코레이터의 슈퍼클래스는 자신이 장식하고 있는 객체의 슈퍼클래스와 같습니다.
  • 한 객체를 여러개의 데코레이터로 감쌀 수 있습니다.
  • 데코레이터는 자신이 감싸고 있는 객체와 같은 슈퍼클래스를 가지고 있기 때문에 원래 객체(싸여져 있는 객체)가 들어갈 자리에 데코레이터 객체를 집어넣어도 상관없습니다.
  • 데코레이터는 자신이 장식하고 있는 객체에서 어떤 행동을 위임하는 것 외에 원하는 추가적인 작업을 수행할 수 있습니다.
  • 객체는 언제든지 감쌀 수 있기 때문에 실행중에 필요한 데코레이터를 마음대로 적용할 수 있습니다.

그림으로 표현하면 다음과 같습니다.

데코레이터 패턴의 기본적인 형태는 다음과 같습니다.

  • 추상 구성요소 Component
    추상 클래스로 데코레이터로 감싸져 사용될 수 있음.

  • 구현 구성요소 ConcreteComponent
    인터페이스를 동적으로 추가함.

  • 추상 데코레이터 Decorator
    Decorator 안에는 Component 객체를 가짐. 자신이 장식할 구성요소와 같은 인터페이스 또는 추상 클래스를 구현함.

  • 구현 데코레이터 ConcreteDecorator
    Decorator가 감싸고 있는 Component 객체를 위한 인스턴트 변수가 있어 Component 상태를 확장할 수 있음.


데코레이터 패턴 사용해 주문 시스템 만들기

  • Component = Beverage
  • ConcreteComponent = HouseBlend, Espresso 등 ..
  • Component를 채택하는 Decorator
    내부에 Component의 타입 변수를 가지고 있음
  • ConcreteDecorator = Mocha, Soy, Whip 등 ..


이런식으로 커피를 커스텀하는 것에 대해 데코레이터 패턴을 사용할 수 있습니다.

데코레이터 패턴의 장단점

장점

  • 상속을 통한 하위 클래스를 만들지 않고도 객체의 기능을 확장할 수 있습니다.
  • 런타임에서 객체에 책임을 추가하고 제거할 수 있습니다.
  • 객체를 여러 데코레이터로 래핑하여 여러 동작을 합칠 수도 있습니다.
  • 객체 지향 프로그래밍에서 중요한 단일 책임 원칙을 지킬 수 있습니다.

단점

  • 래퍼 스택에서 특정 래퍼를 제거하는 것은 어렵습니다.
  • 데코레이터 기능이 데코레이터 스택 순서에 의존해야 합니다.
  • 코드가 복잡해질 수 있습니다.
profile
Don't think, just do 🎸

0개의 댓글