이번에는 스타버즈 커피샵(스타벅스..?)에서 다양한 음료들을 모두 포괄하는 주문 시스템을 만드려 합니다.
기존의 시스템을 상속을 이용해서 바꿔봅시다.
옵션 선택사항을 슈퍼클래스 Beverage에 포함시키고, 음료를 서브클래스로 구현합니다.
하지만 이렇게 구현할 경우
효율적이지 못할 뿐더러 디자인 원칙 중 하나인 개방 폐쇄 원칙에 어긋나게 됩니다.
디자인 원칙
OCP (Open-Closed Principle)
클래스는 확장에 대해서는 열려 있어여 하지만 코드 변경에 대해서는 닫혀 있어야 한다.
상속을 써서 음료 가격과 첨가물(샷, 시럽, 우유, 휘핑 크림 등) 가격을 합한 총 가격을 계산하는 방법은 그리 좋은 방법이 되지 못했습니다.
그래서 우리가 대신 사용할 방법은 다음과 같습니다.
특정 음료에서 시작해서 첨가물로 음료를 장식하는(Decorate) 방법
입니다.
DarkRoasat
객체에서 시작합니다.Mocha
객체를 만들고 그 객체로 DarkRoast
를 감쌉니다.Whip
데코레이터를 만들고 그 객채로Mocha
를 감쌉니다.Whip
의 cost()
를 호출하면 됩니다. 그러면 Whip
에서는 그 객체가 장식하고 있는 객체에게 가격 계산을 위임합니다. 가격이 구해지고 나면 구해진 가격에 휘핑크림의 가격을 더한 다음 그 결과를 리턴합니다.데코레이터 패턴에서는 객체의 추가적인 요건을 동적으로 첨가합니다.
데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공합니다.
그림으로 표현하면 다음과 같습니다.
데코레이터 패턴의 기본적인 형태는 다음과 같습니다.
추상 구성요소 Component
추상 클래스로 데코레이터로 감싸져 사용될 수 있음.
구현 구성요소 ConcreteComponent
인터페이스를 동적으로 추가함.
추상 데코레이터 Decorator
Decorator 안에는 Component 객체를 가짐. 자신이 장식할 구성요소와 같은 인터페이스 또는 추상 클래스를 구현함.
구현 데코레이터 ConcreteDecorator
Decorator가 감싸고 있는 Component 객체를 위한 인스턴트 변수가 있어 Component 상태를 확장할 수 있음.
Beverage
HouseBlend
, Espresso
등 ..Decorator
Mocha
, Soy
, Whip
등 ..이런식으로 커피를 커스텀하는 것에 대해 데코레이터 패턴을 사용할 수 있습니다.