헤드퍼스트 디자인패턴 정리 13, 14 - 실전 디자인 패턴과 기타 패턴

헤드퍼스트 디자인패턴 정리 13, 14 - 실전 디자인 패턴과 기타 패턴

헤드퍼스트 디자인패턴 책을 읽으면서 주요 내용을 정리해놓은 노트를 공개합니다.

헤드퍼스트 디자인패턴 13장과 14장에서 나온 패턴에 대해 요약정리한 내용입니다.

13장

실전에서 패턴을 활용하는 데 도움이 될 팁들을 소개하고, 지금까지 배운 디자인 패턴을 정리한다.

디자인 패턴 정리

  1. 전략 패턴
    교환 가능한 행동을 캡슐화하고 위임으로 어던 행동을 사용할지 결정합니다.
  2. 옵저버 패턴
    상태가 변경되면 다른 객체들에게 연락을 돌릴 수 있게 해 줍니다.
  3. 데코레이터 패턴
    객체를 감싸서 새로운 행동을 제공합니다.
  4. 팩토리 메소드 패턴
    생성할 구상 클래스를 서브 클래스에서 결정합니다.
  5. 추상 팩토리 패턴
    클라이언트에서 구상 클래스를 지정하지 않으면서도 객체군을 생성할 수 이 있도록 해줍니다.
  6. 싱글턴 패턴
    딱 한 객체만 생성되도록 합니다.
  7. 커맨드 패턴
    요청을 객체로 감쌉니다.
  8. 어댑터 패턴
    객체를 감싸서 다른 인터페이스를 제공합니다.
  9. 퍼사드 패턴
    일련의 클래스에 간단한 인터페이스를 제공합니다.
  10. 템플릿 메소드 패턴
    알고리즘의 개별 단계를 구현하는 방법을 서브클래스에서 결정합니다.
  11. 반복자 패턴
    컬렉션이 어떤 식으로 구현되었는지 드러내지 않으면서도 컬렉션 내에 있는 모든 객체를 대상으로 반복 작업을 처리할 수 있게 해줍니다.
  12. 컴포지트 패턴
    클라이언트에서 객체 컬렉션과 개별 객체를 똑같이 다룰 수 있도록 해 줍니다.
  13. 상태 패턴
    상태를 기반으로 하는 행동을 캡슐화한 다음 위임으로 필요한 행동을 선택합니다.
  14. 프록시 패턴
    객체를 감싸서 그 객체로의 접근을 제어합니다.

디자인패턴 분류

생성, 행동, 구조라는 3가지 범주로 용도에 따라 디자인패턴을 나눌 수 있다.

  • 생성패턴 (Creational Pattern)
    객체 인스턴스를 생성하는 패턴. 클라이언트와 그 클라이언트가 생성해야하는 객체 인스턴스 사이의 연결을 끊어주는 패턴. (ex. 싱글턴, 추상 팩토리, 팩토리 메소드)
  • 행동패턴 (Behavioral Pattern)
    클래스와 객체들이 상호작용하는 방법과 역할을 분담하는 방법을 다루는 패턴 (ex. 템플릿 메소드, 싱글턴, 반복자, 옵저버, 상태, 전략)
  • 구조패턴 (Structrual Pattern)
    클래스와 객체를 더 큰 구조로 만들 수 있게 구상을 사용하는 패턴 (ex. 데코레이터, 어댑터, 컴포지트, 프록시, 퍼사드)

별개로, 클래스를 다루는 패턴인지 객체를 다루는 패턴인지에 따라 분류하기도 한다.

  • 클래스패턴 (Class Pattern)
    클래스 사이의 관계가 상속으로 어떻게 정의되는지를 다룬다. 클래스 사이의 관계는 대부분 컴파일할 때 결정된다. (ex. 템플릿 메소드, 팩토리 메소드, 어댑터)
  • 객체 패턴 (Object Pattern)
    객체 사이의 관계를 다룬다. 객체 사이의 관계는 보통 구성으로 정의된다. 일반적으로 실행 중에 관계가 겨렁되므로 보다 동적이고 유연하다 (ex. 데코레이터, 컴포지트, 프록시, 퍼사드, 커맨드, 반복자, 전략, 옵저버, 상태, 추상 팩토리, 싱글턴…)

기타 패턴

좀 더 다양한 패턴을 가볍게 훑어보는 장.

브리지패턴

구현 뿐만 아니라 추상화된 부분까지 변경시켜야 하는 경우 사용.

만약, 모든 TV를 대상으로 작동하는 리모컨을 만든다고 한다면… 추상화된 부분과 구현 부분을 서로 다른 클래스 계층구조로 분리해서 둘을 모두 변경한다.

  • 활용처
    • 여러 플랫폼에서 사용해야하는 그래픽스와 윈도우 처리 시스템에서 유용하게 사용됨.
  • 장점
    • 구현과 인터페이스를 완전히 결합하지 않았기에 구현과 추상화 부분을 분리할 수 있음.
  • 단점
    • 디자인이 복잡해진다

빌더 패턴

제품을 여러단계로 나눠서 만들도록 제품 생산 단계를 캡슐화하고 싶을 때 사용.

만약, 테마 파크에서 고객에게 제공할 휴가 계획 프로그램이 있다고 치자. 휴가계획은 날짜별로 세워야 하므로, 다양한 손님의 계획표를 표현할 수 있는 유연한 자료구조가 필요하다.

계획표 작성을 객체(빌더라고 부름)에 캡슐화해서 클라이언트가 빌더에게 계획표 구조를 만들어 달라고 요청하도록 만든다.

  • 활용법
    복합 객체 구조를 구축하는 용도로 많이 쓰임.
  • 장점
    복합 객체 생성 과정을 캡슐화. 팩토리 패턴과 비교했을 때 보다 여러 단계와 다양한 절차를 거쳐 객체를 생성할 수 있음. 클라이언트는 추상 인터페이스만 볼 수 있기에 제품을 구현한 코드를 쉽게 바꿀 수 있다.
  • 단점
    팩토리를 사용할 때보다 객체를 만들 때 클라이언트에 관해 더 많이 알아야 함.

책임 연쇄 패턴

1개의 요청을 2개 이상의 객체에서 처리해야할 때 사용.

예를 들어, 각 메일을 필요한 담당부서에게 주거나 삭제해야한다면…

주어진 요청을 검토하는 객체 사슬을 생성하고, 그 사슬에 속해 있는 각 객체는 자기가 받은 요청을 검사해서 직접 처리하거나 사슬에 들어있는 다른 객체에게 넘긴다.

이메일이 수신되면 첫 번째 핸들러인 SpamHandler에게 전달되고, SpamHandler가 처리할 수 없으면 FanHandler로… 쭉 사슬을 따라 요청이 전달되고 적절한 핸들러가 메일을 분류함.

  • 활용법
    윈도우 시스템에서는 마우스 클릭과 키보드 이벤트를 처리할 때 흔히 사용됨.
  • 장점
    요청을 보낸 쪽과 받는 쪽 분리 가능  사슬에 들어가는 객체를 바꾸거나 순서를 바꿈으로써 역할을 동적으로 추가하거나 제거가능  객체는 사슬의 구조를 몰라도 됨 + 사슬에 들어있는 다른 객체의 직접적인 레퍼런스를 가질 필요도 없음 = 객체가 단순해짐
  • 단점
    요청이 반드시 수행된다는 보장이 없음. 사슬 끝까지 갔는데도 처리되지 않을 수 있음 실행 시 과정을 살펴보거나 디버깅하기가 힘들다.

플라이웨이트 패턴

어떤 클래스의 인스턴스 하나로 여러 개의 ‘가상 인스턴스’를 제공하고 싶을 때 사용.

예를들어, 수천그루의 나무를 표시하는 데 너무 많은 리소스가 들어 애플리케이션이 너무 느려졌다고 하자.

Tree 객체를 수 천 개 만드는 대신 시스템을 조금 고쳐서 Tree의 인스턴스는 하나만 만들고 모든 나무의 상태를 클라이언트 객체가 관리하도록 하자.

  • 활용법
    어떤 클래스의 인스턴스가 아주 많이 필요하지만 모두 똑같은 방식으로 제어해야 할 때
  • 장점
    메모리 절약. 여러 가장 객체의 상태를 한 곳에 모아둘 수 있음.
  • 단점
    특정 인스턴스만 다른 인스턴스와 다르게 행동하게 할 수 없다

인터프리터 패턴

어떤 언어의 인터프리터를 만들 때 사용.

 문법과 구문을 번역하는 인터프리터 클래스를 기반으로 간단한 언어를 정의한다.

 

  • 활용법
    간단한 언어를 구현할 때 유용하다 효율보다는 단순하고 간단하게 문법을 만드는 것이 더 중요한 경우.
  • 장점
     문법이 클래스로 표현되므로 언어를 쉽게 변경하거나 확장 가능
  • 단점
    문법 규칙의 개수가 많아지면 아주 복잡해진다.

중재자 패턴

: 서로 관련된 객체 사이의 복잡한 통신과 제어를 한곳으로 집중하고 싶을 때 사용

예를 들어, 자동화 주택에서 각 요일별로 작동한다고 해보자…

  • 활용법
    서로 연관된 GUI 구성 요소를 관리하는 용도 객체가 너무 복잡해질 수 있다
  • 장점
    코드 재사용성
  • 단점
    디자인을 잘 하지 못하면 중재자 객체가 너무 복잡해질 수 있다

메멘토 패턴

객체를 이전의 상태로 복구해야 할 때 사용. (‘작업 취소’ 요청)

만약, 게임에서 세이브 기능을 만든다면…

  • 시스템에서 핵심적인 기능을 담당하는 객체의 상태 저장
  • 심적인 객체의 캡슐화 유지

  • 활용처
    아까 말했듯이 취소요청 등 상태를 저장해놓는 코드에서 활용
  • 장점
    저장된 상태를 핵심 객체와는 다른 별도의 객체에 보관 (캡슐화된 상태로 유지)
  • 단점
    상태를 저장하고 복구하는 데 시간이 오래 걸릴 수 있음

프로토타입 패턴

어떤 클래스의 인스턴스를 만들 때 자원과 시간이 많이 들거나 복잡할 때 사용.

만약, 롤플레잉 게임에 다양한 몬스터가 주변 지형에 맞춰서 특성이 바뀐다면

  • 활용법
    시스템에서 복잡한 클래스 계층구조에 파묻혀 있는 다양한 형식의 객체 인스턴스를 새로 만들어야 할 때.
  • 장점
    클라이언트는 새로운 인스턴스를 만드는 과정을 몰라도 됨

비지터 패턴

다양한 객체에 새로운 기능을 추가해야 하는데 캡슐화가 별로 중요하지 않다면 사용.

만약에, 메소드가 지속적으로 추가되는 구조라면

  • 장점
    비교적 손쉽게 새로운 기능을 추가할 수 있음
  • 단점
    컬렉션 내의 모든 항목에 접근하는 트래버서가 있으므로 복합 구조를 변경하기가 더 어려워짐.

© 2022. All rights reserved.