책너두 (헤드 퍼스트 디자인 패턴) 8일차 (~125p)

요약

  • 객체 꾸미기 (데코레이터 패턴)
    • 초대형 커피 전문점, 스타버즈
    • OCP 살펴보기
    • 데코레이터 패턴 살펴보기
    • 주문 시스템에 데코레이터 패턴 적용하기
    • 데코레이터 패턴의 정의

메모

CHAPTER 03. 객체 꾸미기 (데코레이터 패턴)

  • 데코레이터 패턴을 이용하면 기존 클래스 코드를 바꾸지 않고도 객체에 새로운 임무를 추가할 수 있음.

초대형 커피 전문점, 스타버즈

  • 초기 스타버즈의 주문 시스템은 다음과 같음.
  • Beverage 추상 클래스
    • 서브 클래스는 음료들
    • 여기서 문제는, 음료에 우유, 두유, 모카, 휘핑크림을 추가할 때마다 그에 대한 서브 클래스를 만들었음.
      • 클래스가 너무 많아지는 문제가 생김.
    • 그래서, 인스턴스 변수로 첨가물을 관리하면 어떨지 생각함.
      • 첨가물에 대한 비용을 인스턴스로 관리하면, cost 메서드를 서브클래스에서 슈퍼 클래스 cost 메소드 호출과 함께 서브클래스의 가격을 더해주면 되긴 함.
        • 그러나 이렇게 하면, 첨가물 가격이 바뀔 때마다 기존 코드를 수정해야 함.
        • 첨가물 종류가 많아지면 새로운 메소드를 추가해야하고, 슈퍼 클래스 cost 메소드도 고쳐야 함.
        • 새로운 음료가 출시 됐을 때, 특정 첨가물이 들어가면 안되는 음료인데도 서브 클래스에서 상속을 받게 되는 문제가 발생함.
        • 첨가물이 1개가 아니라 2라면…

OCP 살펴보기

  • OCP(Open-Closed Principle)은 정말 중요한 디자인 원칙 중 하나임.
📍 디자인 원칙 : 클래스는 확장에는 열려 있어야 하지만 변경에는 닫혀 있어야 한다.
  • 우리의 목표는 기존 코드를 건드리지 않고 확장으로 새로운 행동을 추가하는 것임.
    • 새로운 기능을 추가할 때 급변하는 주변 환경에 잘 적응하여 유연하고 튼튼한 디자인을 만들 수 있음.
  • 옵저버 패턴의 경우, 옵저버를 새로 추가하면, 주제에 코드를 추가하지 않아도 얼마든지 확장할 수 있음.
  • OCP를 지키다 보면 새로운 단계의 추상화가 필요함. → 코드가 복잡해 짐
    • 그래서 디자인한 것 중, 가장 바뀔 가능성이 높은 부분을 중점적으로 살펴보고 OCP를 적용하는 방법이 가장 좋음.

데코레이터 패턴 살펴보기

  • 첨가물로 음료를 장식해볼 수 있음.
  • ex) 다크 로스트 커피를 주문
    • DarkRoast 객체를 가져옴.
    • Mocha 객체로 장식함.
    • Whip 객체로 장식함.
    • cost() 메소드를 호출함.
      • 첨가물의 가격을 계산하는 일은 해당 객체에게 위임함.

주문 시스템에 데코레이터 패턴 적용하기

  • 다크로스트 객체에서 시작
  • 고객이 모카를 주문함 → 모카 객체가 다크 로스트 객체를 감싼다.
    • 이 모카 객체의 형식은 객체가 장식하고 있는 객체(다크 로스트 객체)를 반영함.
    • 반영한다는 의미는 “같은 형식을 갖는다” 라고 이해하면 됨.
    • 따라서, 모카 객체도 cost 메소드가 있음.
  • 고객이 휘핑 크림도 주문함 → 휘핑 크림 객체가 모카 객체를 감싼다.
  • 이제 가격을 계산하면, 가장 바깥쪽 데코레이터의 cost 메소드를 호출한다.
    • 그럼 모카 객체의 cost, 다크 로스트 객체의 cost 메소드가 차례로 불리면서 첨가물의 가격이 모두 계산된 최종 금액을 리턴한다.

정리

  • 데코레이터의 슈퍼 클래스는 자신이 장식하고 있는 객체의 슈퍼클래스와 같음.
  • 한 객체를 여러 개의 데코레이터로 감쌀 수 있음.
  • 데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 일 말고도 추가 작업을 수행할 수 있음.
  • 객체는 언제든지 감쌀 수 있으므로 실행 중에 필요한 데코레이터를 마음대로 적용할 수 있음.

데코레이터 패턴의 정의

📍 데코레이터 패턴(Decorator Pattern)으로 객체에 추가 요소를 동적으로 더할 수 있음. 데코레이터를 사용하면 서브클래스를 만들 때보다 훨씬 유연하게 기능을 확장할 수 있음.

  • 데코레이터 안에 구성 요소의 레퍼런스를 포함한 인스턴스 변수가 있음.
  • 컴포넌트 구현체에서 새로운 행동을 동적으로 추가할 수 있음.

댓글

Designed by JB FACTORY