3. 객체 꾸미기: 데코레이터 패턴
<aside>
💡 디자인 원칙
OCP(Open-Closed-Principle): 클래스는 확장에는 열려 있어야 하지만 변경에는 닫혀 있어야 한다.
</aside>
- 코드에서 확장할 부분을 선택하는 것이 중요 → 무조건 OCP를 적용한다면 필요이상으로 복잡하고 이해하기 힘든 코드를 작성하게 되는 부작용이 생길 수 있다.
데코레이터 패턴 살펴보기 (with 스타벅스 예제)
- 어떤 고객이 모카와 휘핑크림을 추가한 다크로스트 커피를 주문하는 경우
- DarkRost 객체를 가져온다
- Beverage 상속받음. cost 메소드 가지고있음
- Mocha 객체로 장식한다
- Mocha 객체 == 데코레이터
- 객체의 형식은 객체가 장식하고 있는 객체의 형식을 반영(mirror, 같은 형식을 갖는다)한다.
- 따라서 Mocha에도 cost 메소드가 있고 Mocha가 감싸고 있는 것도 Beverage 객체로 간주 가능.
- Whip 객체로 장식한다
- Whip 객체 == 데코레이터
- cost 메소드 가짐
- cost() 메소드를 호출한다. 이때 첨가물의 가격을 계산하는 일은 해당 객체에게 위임한다.
- 가장 바깥쪽에 있는 데코레이터인 Whip의 cost 메소드 호출
- Whip은 Mocha의 cost 메소드 호출
- Mocha는 다시 DarkRoast의 cost 메소드 호출
- DarkRoast 값 리턴
- Mocha는 리턴받은 값에 Mocha 가격을 더하여 리턴
- Whip은 리턴받은 값에 Whip 가격을 더해 최종 가격 리턴
데코레이터 패턴 특징
- 데코레이터의 슈퍼클래스는 자신이 장식하고 있는 객체의 슈퍼 클래스와 동일
- 한 객체를 여러 개의 데코레이터로 감쌀 수 있음
- 데코레이터는 자신이 감싸고 있는 객체와 같은 슈퍼 클래스를 가지고 있기에 원래 객체(싸여 있는 객체)가 들어갈 자리에 데코레이터 객체를 넣어도 괜찮음
- 데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 일 말고도 추가 작업 수행 가능
- 객체는 언제든지 감쌀 수 있으므로 실행 중에 필요한 데코레이터를 마음대로 적용할 수 있다.
데코레이터 패턴 정의