Home [CS] 디자인패턴 - 구조패턴
Post
Cancel

[CS] 디자인패턴 - 구조패턴

구조패턴

클래스나 객체를 조합해 더 큰 구조를 만드는 패턴이다.

예를 들면 서로 다른 인터페이스를 지닌 2개의 객체를 묶어서 단일 인터페이스로 제공하거나, 서로 다른 객체들을 묶어 새로운 기능을 제공하는 패턴이 있다.

어댑터(Adapter)

호환되지 않는 인터페이스들을 연결하는 디자인 패턴이다.

호출당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출한다.

사용

  • 호환되지 않는 인터페이스를 가진 클래스들이 함께 작동해야 하는 경우
  • 이미 존재하는 클래스의 인터페이스가 요구 사항과 맞지 않거나 또는 기존 클래스에 원하는 인터페이스가 없는 경우

예시

  • 자바의 I/O 라이브러리 InputStreamReader InputStreamReader는 바이트 스트림을 문자 스트림으로 변환하는 어댑터 역할을 한다. 이 클래스는 InputStream을 받아서 Reader를 제공함으로써 바이트를 문자로 변환한다.

장/단점

  • 장점
    • 기존의 클래스를 수정하지 않고도 클라이언트에서 새로운 인터페이스를 사용할 수 있다 👉 코드 재사용, 코드 중복 감소
    • 클라이언트 간의 결합도를 줄여줘서 소스코드 변경이 필요할 때 쉽게 수정할 수 있다.
  • 단점
    • 어댑터 클래스를 추가로 작성해야해서 소스코드가 늘어난다. 👉 코드 복잡성 증가, 유지보수가 어려워짐
    • 어댑터가 중간에 데이터를 변환하는 과정에서 추가적인 처리 시간과 오버헤드가 발생할 수 있다.

브릿지(Bridge)

기능을 처리하는 클래스와 구현을 담당하는 추상 클래스로 구별하는 패턴이다. 구현부에서 추상층을 분리한 것으로 각자 독립적으로 변형이 가능하고 확장이 가능하도록 한다.

사용

  • 부모 추상 클래스가 기본 규칙 세트를 정의하고 구체적인 클래스가 추가 규칙을 추가하고 싶은 경우
  • 객체에 대한 참조가 있는 추상 클래스가 있고 각 구체적인 클래스에서 정의될 추상 메서드가 있는 경우

장/단점

  • 장점
    • 클래스 계층을 분리할 때 완전한 인터페이스를 결합하지 않는다. 이를 통해 구현과 추상 부분 2개의 계층으로 분리될 수 있고, 각각 독립적인 확장이 가능하다.
    • 런타임 시점에 어떤 방식으로 기능을 구현할지 선택할 수 있다.
    • 기능을 독립적으로 확장할 수 있어서 상세한 기능을 외부로부터 숨길 수 있는 은닉 효과도 얻을 수 있다.
  • 단점
    • 추상화를 통해 코드를 분리할 경우 코드 디자인 설계가 복잡해진다.

복합체(컴포짓, Composite)

객체 간의 계층적 구조화를 통해 객체를 확장하는 패턴이다.

  • 복합 객체는 객체가 또 다른 객체를 포함하는 것
  • 복합적인 객체 관계를 복합화 또는 집단화라고 한다.
  • 복합체 패턴을 이용하면 객체의 상위, 하위 체계를 파악할 수 있고 일대일, 다대일을 처리하는 데에도 매우 유용하다.

사용

  • 트리 모양을 가진 구성 요소들을 구현하고 싶은 경우
  • 객체에 따라 다르게 처리하지 않고 동일하게 취급해야할 때

예시

  • 회사와 부서, 팀과 같이 그룹과 해당 그룹에 속한 하위 그룹이 있는 계층(트리) 구조 형태
  • 세트 상품 (다른 세트 상품의 일부가 될 수 있음)

장/단점

  • 장점
    • 단일 객체와 복합 객체(그룹)을 동일하게 여기기 때문에, 묶어서 연산하거나 관리할 때 편하다.
    • 투명성을 이용해서 클라이언트의 사용을 단순화할 수 있다. (if문을 사용하지 않고 Composite와 Leaf 판단이 가능하다.)
  • 단점
    • 재귀 호출 특징 상 트리의 Depth가 깊어질수록 디버깅에 어려움이 생긴다.
    • 수평적, 수직적 모든 방향으로 객체를 확장할 수 있지만, 수평적 방향으로만 확장하도록 Leaf를 제한한 Composite를 만들기는 어렵다.

프록시(Proxy)

제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴이다.

실제 객체를 호출하면 중간에 가로채서 다른 동작을 수행하는 객체로 변경한다.

사용

  • 객체를 정교하게 제어해야하거나, 객체 참조가 필요한 경우

장/단점

  • 장점
    • 사이즈가 큰 객체가 로딩되기 전에도 프록시를 통해 참조를 할 수 있다.
    • 실제 객체의 public, protected 메소드를 숨기고 인터페이스를 통해 노출시킬 수 있다.
    • 로컬에 있지않고 떨어져있는 객체도 사용할 수 있다.
    • 실제 객체의 접근에 대해 사전처리를 할 수 있다.
  • 단점
    • 객체를 생성할 때 한 단계를 거치게되므로, 빈번한 객체 생성이 필요한 경우 성능이 저하될 수 있다.
    • 프록시 내부에서 객체 생성을 위해 스레드 생성 및 동기화가 구현되어야하는 경우 성능이 저하될 수 있다.
    • 로직이 난해해져서 가독성이 떨어질 수 있다.

장식자(데코레이터, Decorator)

메서드 호출의 반환값에 변화를 주기 위해 중간에 장식자를 두는 패턴이다.

프록시 패턴과 비교

프록시 패턴과 구현 방법은 같다. 하지만 프록시 패턴은 반환값을 조작하지 않고 그대로 리턴하는 반면, 데코레이터 패턴은 클라이언트가 받는 반환값에 장식을 덧입힌다.

패턴특징
프록시 패턴- 제어의 흐름을 변경하거나 별도의 로직 처리를 목적으로 한다.
- 클라이언트가 받는 반환값을 특별한 경우가 아니면 변경하지 않는다.
데코레이터 패턴- 클라이언트가 받는 반환값에 장식을 더한다.

사용

기존의 객체를 감싸서 새로운 기능을 추가하는 객체를 생성할 때

장/단점

  • 장점
    • 상속 형태의 확장보다 더 융통성있게 설계가 가능하다.
    • 객체 실행 중에도 동적으로 기능을 추가할 수 있어서 새로운 부가 기능을 추가하는 가장 효과적인 방법이다.
    • 클래스 등의 자원을 미리 생성해서 낭비하지않고 동적으로 처리되는 시점에 할당받아서 사용할 수 있다.
  • 단점
    • 유사한 성질의 작은 클래스들이 증가한다. (상호작용방법에만 차이가 있는 클래스들)
    • 기존 객체를 감싸는 과정이 있어야하므로 구성 요소를 초기화하는 작업이 필요하다.

퍼사드(Facade)

Facade는 프랑스어로 건물의 정면을 의미하며, 어떤 소프트웨어의 커다란 코드 부분에 대해서 간략화된 인터페이스를 제공해주는 패턴이다.

메인 시스템과 서브 시스템 중간에 위치하여 새로운 인터페이스 계층을 추가해서 시스템 간 의존성을 해결한다.

인터페이스 계층은 메인 시스템과 서브 시스템의 연결 관계를 대신 처리한다.

사용

  • 서브 시스템이 복잡하고 종속성이 강할 때
  • 서브 시스템을 공통적으로 사용할 수 있도록 할 때

장/단점

  • 장점
    • 서브 시스템 보호 : 서브 시스템의 구성요소를 직접 호출하지 않아서 잘못된 사용을 방지한다.
    • 확장성 : 코드 변경 시 상위 시스템에서는 퍼사드를 이용하므로 서브 시스템이 변경되어도 큰 변화를 느낄 수 없다. (업그레이드에 자유로움)
    • 결합도 감소 : 복잡한 종속적 결함도를 낮추고 독립적인 코드 유지가 가능하다.
    • 계층화 : 서브 시스템이 계층화된 구조를 갖더라도 퍼사드는 계층 단계별로 접근하여 행위를 호출할 수 있다.
    • 이식성 : 서브 시스템을 공통적으로 사용할 수 있도록 이식성을 향상시킨다.
    • 공개 인터페이스 : 외부에 공개되는 기능과 공개되지 않는 기능을 구분할 수 있다.
  • 단점
    • 퍼사드가 모든 클래스에 결합된 God 객체가 될 수 있다.
    • 퍼사드 클래스 자체가 서브시스템에 대한 의존성을 가지게 되어 의존성을 완전히 피할 수는 없다.
    • 추가적인 코드가 늘어나서 유지보수가 어려워진다.

플라이웨이트(Flyweight)

fly(가볍다) + weight(무게) = 중복되는 코드의 객체를 공유해서 메모리를 적게 할당하도록 하여 무게가 가벼움

객체를 공유함으로써 객체를 재사용해서 시스템을 절약할 수 있는 패턴이다.

팩토리 클래스에 공유 저장소를 추가하여 객체의 중복 생성 동작을 제한한다.

사용

  • 대량의 객체를 생성하고 관리할 경우
  • 관리하는 객체의 수가 많아서 처리하기 힘든 경우

예제

  • 자바에서 String 객체를 생성하는 리터럴 방식의 String Constanct Pool

장/단점

  • 장점
    • 무분별하게 객체를 생성하지 않고 기존 객체를 참조함으로써 중복을 방지한다.
    • 기존의 객체를 사용한 후 삭제하지 않고 재사용 혹은 공유할 경우 메모리 자원을 절약하고, 객체를 생성하는 자원과 시간도 절약할 수 있다.
  • 단점
    • 공유 객체가 상태 값에 종속적인 상태면 플라이웨이트 패턴으로 공유할 수 없다. 객체 상태가 변경됨으로써 참조하는 다른 객체에 사이드 이펙트 효과가 발생하기 떄문이다.

출처

This post is licensed under CC BY 4.0 by the author.

[CS] 디자인패턴 - 생성패턴

[CS] 디자인패턴 - 행동패턴