디자인 패턴 정리(2) - Structural Pattern

냥무룩·2022년 2월 21일
0

디자인패턴

목록 보기
2/3

어댑터(Adapter)

어댑터 패턴은 서로 다른 인터페이스를 가진 두 클래스를
어댑터 클래스로 인터페이스를 통일 시켜 사용하는 방법이다.

서로 다른 두 클래스(Client 와 Adaptee) 가 있고, 이 둘은 그대로 둔 채 이 둘의 인터페이스를 연결하고자 어댑터 클래스를 만들어 사용하는 구조를 어댑터 패턴이라고 한다.
이 패턴은 이미 정의된 3자의 인터페이스를 자신의 인터페이스의 모양으로 "인터페이스의 변경" 하고 싶을 때 사용한다.

장점

  • 기존 클라이언트 단의 코드 수정 최소화.
  • 클라이언트는 연동부분을 몰라도, 새로운 코드의 기능을 일관되게 사용가능.

단점

어댑터 클래스에서 통일 시켜주는 부분을 하나씩 구현해야 함.

구조

컴퍼지트(Composite)

컴퍼지트 패턴은 단일 객체와 그 객체들을 가지는 집합 객체를
같은 타입으로 취급하며, 트리 구조로 객체들을 엮는 패턴이다.

여러 개의 클래스가 크게 보면 같은 요소(Component) 에 속하지만, 여기에 속한 어떤 클래스(Composite)가 자기 자신 혹은 다른 클래스(Leaf)를 가질 수 있는 구조를 컴퍼지트 패턴이라고 한다.
이 패턴은 같은 개념의 클래스들 간에 소유 개념을 나타낸 트리 형태 묶고 싶을 때 사용한다.

장점

  • 객체들이 모두 같은 타입으로 취급되기 때문에 새로운 클래스 추가가 용이하다.
  • 단일객체, 집합객체 구분하지 않고 코드 작성이 가능하다.

단점

설계를 일반화 시켜 객체간의 구분, 제약이 힘들다.

활용상황

  • 객체들 간에 계급 및 계층구조가 있고 이를 표현해야할 때
  • 클라이언트가 단일 객체와 집합 객체를 구분하지 않고 동일한 형태로 사용하고자 할 때

구조

Component

  • Leaf와 Composite 가 구현해야하는 Interface 로, Leaf 와 Composite 는 모두 Component 라는 같은 타입으로 다뤄진다.

Leaf

  • 단일 객체로 Composite 의 부분(자식) 객체로 들어가게 된다.
    이 때, Component 의 형태로 들어간다.

Composite

  • 집합 객체로 Leaf 객체나 Composite 를 부분(자식)으로 둔다.
    이 때, Component 의 형태로 들어간다.
    클라이언트는 이 Composite 를 통해 부분 객체들 (Leaf 나 Composite) 을 다룰 수 있다.

데코레이터 (Decorator)

데코레이터 패턴은 기본 객체에
추가적인 기능을 동적으로 유연하게 첨가하는 패턴이다.

각각의 기능을 담당하는 클래스(Decorator)들과 이 기능을 적용할 클래스(Component)를 분리한 뒤, 필요에 따라 동적으로 각 기능을 적용할 수 있는 구조를 데코레이터 패턴이라고 한다.
이 패턴은 주요 기능에 경우에 따라 부가적인 기능을 추가하거나 빼고 싶을 때 사용한다.

장점

객체에 동적으로 기능 추가가 간단하게 가능하다.

단점

  • 자잘한 데코레이터 클래스들이 계속 추가되어 클래스가 많아질 수 있다.
  • 겹겹이 애워싸고 있기 때문에 객체의 정체를 알기 힘들고 복잡해질 수 있다.

활용 상황

객체가 상황에 따라 다양한 기능이 추가되거나 삭제되어야 할 때.

구조

Component

  • ConcreteComponent 과 Decorator 가 구현할 인터페이스다.
    두 객체를 동등하게 다루기 위해 존재함

ConcreteComponent

  • Decorate 를 받을 객체다.
    즉, 기능 추가를 받을 기본 객체

Decorator

  • Decorate 를 할 객체의 추상 클래스다.
    즉, 기능 추가를 할 객체는 이 객체를 상속받는다.

ConcreteDecorator

  • Decorator 를 상속받아 구현할 다양한 기능 객체이다.
    이 기능들은 ConcreteComponent 에 추가되기 위해 만들어 진다.

프록시

프록시 패턴은 프록시 객체를 통해 기본 객체에 접근하는 패턴이다.

돈을 대출받기 위해 은행에 가본다고 해보자.
일반적으로 은행에서는 기본적으로 대출 담당자가 대출 관련 업무를 처리해준다.
그런데 내가 찾아간 은행 A에서는 대출 담당자 이전에 대출 안내 담당자가 나를 먼저 맞이하여 준다.
이 담당자를 통해 간단한 서류 작성을 하거나(전처리), 내가 이전에 대출한 기록이 있는 경우 대출 담당자를 통하지 않고도 바로 대출(캐싱)을 해주고 있다.

이처럼, 구체적인 업무를 담당하고 있는 클래스에 접근하기 전에, 간단한 사전 작업 처리하는 클래스(Proxy)를 두는 구조를 프록시 패턴이라고 한다.
이 패턴은 주요 기능이 요청을 받아 수행하기 전에, 이 요청에 대한 부가적인 전처리들을 수행하는 로직을 세우고 싶을 때 사용한다.

장점

  • 기본 객체의 리소스가 무거운 경우, 프록시 객체에서 간단한 처리를 하거나 기본 객체를 캐싱 처리함으로써 부하를 줄일 수 있다.
  • 기본 객체에 대한 수정 없이, 클라이언트에서의 사용과 기본 객체 사이에 일련의 로직을 프록시 객체를 통해 넣을 수 있다.
  • 프록시는 기본 객체와 요청 사이에 있기 때문에, 일종의 방패(보안)의 역할도 한다.

단점

프록시 객체가 중간에 껴있기 때문에, 간혹 응답이 느려질 수 있다. (캐싱이 안되어있는 초기 사용의 경우)

활용 상황

  • 기본 객체가 리소스 집약적인 경우. 자잘한 작업들은 프록시 객체가 처리하게 한다.

  • 기본 객체에 접근을 제어해야하는 경우. 프록시 객체가 권한에 따라 접근 로직을 다르게 처리하게 한다.

Subject

  • Proxy 와 RealSubject 가 구현해야하는 인터페이스
    두 객체를 동일하게 다루기 위해 존재

Proxy

  • RealSubect 와 Client 요청 사이에 존재하는 객체
    Subject 를 구현함으로써 클라이언트는 RealSubject 사용하는 것과 별 차이가 없어야 한다.

RealSubject

  • 실질적으로 요청에 대해 주된 기능을 수행하는 객체
    Proxy 객체는 내부적으로 이 객체를 로직에 맞게 사용한다. (위임)

0개의 댓글