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

요약

  • 실전 디자인 패턴
    • 책임 연쇄 패턴
    • 플라이웨이트 패턴
    • 인터프리터 패턴
    • 중재자 패턴
    • 메멘토 패턴
    • 프로토타입 패턴
    • 비지터 패턴

메모

책임 연쇄 패턴

  • 1개의 요청을 2개 이상의 객체에서 처리해야 한다면 책임 연쇄(Chain of Responsibility) 패턴을 사용하면 됨.
  • ex) 스팸 메일, 팬 메일, 항의 메일, 신규 설치 요청 메일을 분류해야 함.
    • 검출기를 써서 메일 분류하는 디자인을 만들어야 함.
  • 책임 연쇄 패턴은 주어진 요청을 검토하는 객체 사슬을 생성함.
    • 사슬 속에 속해 있는 각 객체는 자기가 받은 요청을 검사해서 직접 처리하거나 사슬에 들어있는 다른 객체에게 넘김
    • p637 참고
  • 장점
    • 요청을 보낸 쪽과 받는 쪽을 분리할 수 있음
    • 객체는 사슬의 구조를 몰라도 되고 그 사슬에 들어있는 다른 객체의 직접적인 레퍼런스를 가질 필요도 없으므로 객체를 단순하게 만들 수 있음.
    • 사슬에 들어가는 객체를 바꾸거나 순서를 바꿈으로써 역할을 동적으로 추가하거나 제거할 수 있음.
  • 활용법
    • 윈도우 시스템에서 마우스 클릭과 키보드 이벤트를 처리할 때 흔히 쓰임
  • 단점
    • 요청이 반드시 수행된다는 보장이 없음.
      • 사슬 끝까지 갔는데도 처리되지 않을 수 있음.
    • 실행 시에 과정을 살펴보거나 디버깅하기 힘듦.

플라이웨이트 패턴

  • 어떤 클래스의 인스턴스 하나로 여러 개의 ‘가상 인스턴스’를 제공하고 싶다면 이 패턴을 사용하면 됨.
  • ex) 조경 설계 애플리케이션에서 나무를 객체 형태로 추가할 경우 → 나무를 꽤 많이 넣을 경우
    • 실행 중 느려지지 않게 만들어야 함.
    • Tree 객체를 수 천 개 만드는 대신, 시스템을 조금 고쳐서 Tree 인스턴스는 하나만 만들고 모든 나무의 상태를 클라이언트 객체가 관리하도록 함.
  • 장점
    • 실행 시에 객체 인스턴스의 개수를 줄여서 메모리를 절약할 수 있음.
    • 여러 ‘가상’ 객체의 상태를 한곳에 모아 둘 수 있음.
  • 사용법
    • 어떤 클래스의 인스턴스가 아주 많이 필요하지만 모두 똑같은 방식으로 제어해야 할 떄 유용하게 쓰임
  • 단점
    • 이 패턴을 써서 구현해 놓으면 특정 인스턴스만 다른 인스턴스와 다르게 행동하게 할 수 없음.

인터프리터 패턴

  • 어떤 언어의 인터프리터를 만들 때 사용함.
  • ex) 오리 시뮬레이션 게임 → 아이들에게 프로그래밍을 가르쳐줄 용도로한 언어 및 문법 규칙이 필요
    • p640 참고
    • 문법을 완성했다면 아이들이 오리의 움직임을 프로그래밍하고 그 결과를 직접 확인할 수 있도록 문법에 따라 만들어진 코드 해석용 인터프리터를 만들어야 함.
  • 인터프리터 패턴은 문법과 구문을 번역하는 인터프리터 클래스를 기반으로 간단한 언어를 정의함.
    • 언어에 속하는 규칙을 나타내는 클래스를 사용해서 언어를 표현함.
    • p641 참고
  • 장점
    • 문법을 클래스로 표현해서 쉽게 언어를 구현할 수 있음.
    • 문법이 클래스로 표현되므로 언어를 쉽게 변경하거나 확장할 수 있음.
    • 클래스 구조에 메소드만 추가하면 프로그램을 해석하는 기본 기능 외에 예쁘게 출력하는 기능이나 더 나은 프로그램 확인 기능 같은 새로운 기능을 추가할 수 있음.
  • 활용법
    • 간단한 언어를 구현할 때 유용하게 쓰임
    • 효율보다 단순하고 간단하게 문법을 만드는 것이 더 중요한 경우에 유용함.
    • 스크립트 언어와 프로그래밍 언어에서 모두 쓸 수 있음.
  • 단점
    • 문법 규칙의 개수가 많아지면 아주 복잡해짐
      • 파서나 컴파일러 생성기를 쓰는게 나음.

중재자 패턴

  • 서로 관련된 객체 사이의 복잡한 통신과 제어를 한곳으로 집중하고 싶을때 사용함.
  • 객체가 할 일을 정리해야 함.
    • 어떤 객체에 어떤 규칙을 넣어야 할지 어려워짐.
    • 여러 객체를 서로 연관시키는 과정도 복잡함.
  • 시스템에 중재자 패턴을 적용하면 ex)가전 제품 객체들을 훨씬 단순화할 수 있음.
    • 상태가 바뀔 때마다 중재자에게 알려줌.
    • 중재자에게 보낸 요청에 응답함.
  • 장점
    • 시스템과 객체를 분리함으로써 재사용성을 획기적으로 향상시킬 수 있음.
    • 제어 로직을 한 군데 모아놨으므로 관리하기 수월함.
    • 시스템에 들어있는 객체 사이에서 오가는 메시지를 확 줄이고 단순화할 수 있음.
  • 활용법
    • 서로 연관된 GUI 구성 요소를 관리하는 용도로 많이 쓰임
  • 단점
    • 디자인을 잘 하지 못하면 중재자 객체가 너무 복잡해질 수 있음.

메멘토 패턴

  • 객체를 이전의 상태로 복구해야 한다면 이 패턴을 쓰면 됨.
    • ex) 사용자의 ‘작업 취소’ 요청
  • ex) 롤플레잉 게임의 세이브 기능
  • 메멘토 패턴의 2가지 목적
    • 시스템에서 핵심적인 기능을 담당하는 객체의 상태 저장
    • 핵심적인 객체의 캡슐화 유지
  • 장점
    • 저장된 상태를 핵심 객체와는 다른 별도의 객체에 복관할 수 있어 안전함.
    • 핵심 객체의 데이터를 계속해서 캡슐화된 상태로 유지할 수 있음.
    • 복구 기능을 구현하기 쉬움
  • 활용법
    • 메멘토 객체를 써서 상태를 저장함.
    • 자바 시스템에서는 시스템의 상태를 저장할 때 직렬화를 사용하는 것이 좋음.
  • 단점
    • 상태를 저장하고 복구하는 데 시간이 오래 걸릴 수 있음.

프로토타입 패턴

  • 어떤 클래스의 인스턴스를 만들 때 자원과 시간이 많이 들거나 복잡하다면 이 패턴을 쓰면 됨.
  • ex) 몬스터가 주변 환경에 맞춰 몬스터의 특성이 바뀌면 좋겠다.
  • 프로토타입 패턴을 사용하면 기존 인스턴스를 복사하기만 해도 새로운 인스턴스를 만들 수 있음.
    • ex) 자바에서 clone() 메소드를 사용하거나 역직렬화 하면 됨.
    • 클라이언트 코드에서 어떤 클래스의 인스턴스를 만드는지 전혀 모르는 상태에서도 새로운 인스턴스를 만들 수 있음.
  • 장점
    • 클라이언트는 새로운 인스턴스를 만드는 과정을 몰라도 됨
    • 클라이언트는 구체적인 형식을 몰라도 객체를 생성할 수 있음.
    • 상황에 따라 객체를 새로 생성하는 것보다 객체를 복사하는 것이 더 효율적일 수 있음.
  • 활용법
    • 시스템에서 복잡한 클래스 계층 구조에 파묻혀 있는 다양한 형식의 객체 인스턴스를 새로 만들어야 할 때 유용하게 쓸 수 있음.
  • 단점
    • 객체의 복사본을 만드는 일이 매우 복잡할 수도 있음.

비지터 패턴

  • 다양한 객체에 새로운 기능을 추가해야 하는데 캡슐화가 별로 중요하지 않다면 이 패턴을 쓰면 됨.
  • ex) 메뉴에, 영양 정보를 요구하는 손님이 많아짐 → 재료별(메뉴 아이템) 영양정보가 요구하기도 함.
    • 매번 메소드를 추가할 수 없다..
  • 비지터 객체는 트래버서(Traverser) 객체와 함께 돌아감.
    • 트래버서는 컴포지트 패턴을 쓸 때, 복합 객체 내에 속해 있는 모든 객체에 접근을 도와줌.
    • 비지터 객체에서 복합 객체 내의 모든 객체를 대상으로 원하는 작업을 처리하게 해줌.
    • 각각의 상태를 모두 가져오면 클라이언트는 비지터에게 각 상태에 맞는 다양한 작업을 처리하도록 요구할 수 있음.
    • 새로운 기능이 필요하더라도 비지터만 고치면 됨.
  • 장점
    • 구조를 변경하지 않으면서 복합 객체 구조에 새로운 기능을 추가할 수 있음.
    • 비교적 손쉽게 새로운 기능을 추가할 수 있음.
    • 비지터가 수행하는 기능과 관련된 코드를 한 곳에 모아 둘 수 있음.
  • 단점
    • 복합 클래스의 캡슐화가 깨짐
    • 컬렉션 내의 모든 항목에 접근하는 트래버서가 있으므로 복합 구조를 변경하기가 더 어려워 짐.

댓글

Designed by JB FACTORY