'Design Patterns'에 해당되는 글 1건

  1. 2008/03/27 Adapter Pattern (2)

Adapter Pattern

2008/03/27 01:24

Adapter(Wrapper) Pattern

I. 의도

 인터페이스가 일치 하지 않는 클래스들을 원하는 인터페이스로 변환해 함께 동작 시킬 수 있도록 한다.

어댑터 패턴은 데코레이터나 프락시 브릿지 패턴을 이해하는데 도움이 되고 비교하여 차이를 알아야 한다.

Opening Question

  •  목표 인터페이스와 구현클래스의 인터페이스가 동일하게 어탭터 패턴을 적용해 본 적이 있는가?
    그것이 프락시라고 할 수 있나?
    그렇다면 프락시와는 어떤 차이점이 있는 것일까?
  • 어떤 경우에 어탭터가 필요할까?
  • 어댑터를 쓰지 말아야 할 경우는?
  • Webwork의 Intercepter와 비교해보자.

II. 본론

1) 동기

존재하나 현재 이를 사용하고자 하는 클래스와는 아무런 연관 없이 개발된될 클래스나 서로 일치하지 않는 인터페이스를 갖는 클래스들을 홍합하여 하나의 애플리케이션으로 개발해야할경우 기존 코드를 통합하여 운영하고자 할 때


우리가 선택할 수 있는 항목은 아마 다음 두가지 일 것이다.

  •  목표로 하는 인터페이스와 구현이 되어 있는 클래스 둘 다 상속받는 방법
  • 구현 클래스를 포함 시키고 목표로 하는 인터페이스 관점에서 구현하는 것 : 집합관계(Aggregation)을 이용하여 해결
  • 또 무엇이 있을까? Mixin? lamda function?

첫번재 방법을 클래스로 구현하였다.

두번째 방법을 객체로 구현하였다. 라고 표현한다.

동작방식
  • BoundingBox() 오퍼레이션의 구현을 보면, 실제 구현을 제공할 TextView 클래스에 정의된 GetExtent() 메소드를 호출하도록 바꾸어 TextView에 전달한다.: Delegation
  • 기존 클래스가 제공하지 않는 기능성을 제공해야할 경우도 있다. 추가 기능을 처리하는 행위를 추가로 정의함으로 가능하게 된다. (Decoration과 어떤 차이?)

    교재의 구현방식은 Factory Method도 사용되었다.


2) 활용성

  • 기존 클래스를 사용해야 하나 인터페이스가 수정되어야 하는 경우
  • 이미 만들어진 것을 재사용하고자 하나 재사용 가능한 라이브러리를 수정할 수 없는 경우
  • 여러 개의 서브 클래스를 사용해야하는 데 이 서브클래스들의 상속을 통해서 이들의 인터페이스를 다 adaptation 한다는 것이 현실성이 없다면 객체 어댑터 방식으로 부모 클래스의 인터페이스를 변형하는 것이 더 바람직 하다 : lucy 라이브러리

4) 구조

Java 에서는 다중 상속을 지원하지 않기 때문에 1번 방식은 사용할 수 없다. 물론 내부적으로 델리게이션을 사용하는 것은 동일하다.

  1. 다중 상속을 이용한 Adapter 패턴 : super.SpecificRequest()
  2. 객체 합성에 의한 Adapter 패턴

      : adaptee.SepecificRequest()

5) 참여 객체

  • Client : 기능 사용자
  • Target : 목표로 하는 인터페이스
  • Adaptee : 기능을 가지고 있는 객체
  • Adapter : Aaptee의 기능을 가지고 Target의 인터페이스 구현한 객체
6) 협력 방법

 클라이언트는 어댑터에 해당하는 클래스의 인스턴스에게 요청 메세지를 전달하고 어댑터는 변형되는 클래스의 오퍼레이션을 호출한다.

7) 결과
2가지 구현방식의 장단점
  • 클래스 어댑터

    •  Adapter는 명시적으로 Adaptee를 상속받고 있을 뿐 Adaptee의 서브클래스들을 상속받는 것은 아니므로, Adaptee의 서브클래스에 정의된 기능들을 사용할 수 없다.
    • Adaptee에 정의 된 행위(오퍼레이션)을 재정의 할 수 있다.
    • 한 개의 객체만 만들어 낸다. Adapter 객체, Adaptee에 대한 참조자도 필요하지 않다. : 어떤 의미가 있을까? 관리객체수가 적다. 코딩수가 적다.
  • 객체 어댑터

    • 다양하고 많은 Adaptee 클래스와 동작할 수 있다. 하나의 Adapter 클래스로 모든 Adaptee 클래스와 이를 상속받는 서브클래스 모두를 이용할 수 있다.
    • Adaptee 클래스 오퍼레이션 재정의는 어렵다. Adaptee 클래스를 상속받은 새 서브클래스를 만들고 이 서브클래스를 참조하도록 해야 한다.
고려사항
  • adapatation를 위해 수행해야할 일은 어느 정도일까? 구현할 양의 결정 요인은 Target 인터페이스와 Adaptee 간의 얼마만큼의 유사성을 갖는가? 이다.

    • 가장 단순한 인터페이스 변환, 새로운 오퍼레이션 추가는 복잡한 케이스
  • Pluggable Adapter

    • 내가 개발한 클래스를 사용할 모든 클라이언트에게 동일한 인터페이스를 제공해야 한다는 가정을 배제 가능
      하나의 클래스를 설계할 때 모든 클라이언트가 원하는 표준화된 인터페이스를 정의해야한다는 부담을 덜 수 있다.
    • 인터페이스 Adaptation를 담당하는 클래스를 대체할수 있는 어댑터( Pluggable Adapter) 라고 했다.
  • 양방향 어댑터

    • 모든 클라이언트에 적용되지 못한다는 것
    • 서로 다른 두 개의 클라이언트가 객체를 서로 다르게 바라봐야 할 때
    • Adaptation되는 두클래스 모두의 인터페이스를 다 상속 받아 정의 하도록 한다 : Composite와 유사? 
 구현
  1. 클래스 어댑터 방식의 C++

    • Target : public 상속
    • Adaptee : private 상속
    • 양방향 어댑터는 아니구나~
  2. Pluggable Adapter : 3가지 구현 방식

    1.  세 가지 방법 모두에 공통, Adapation가 필요한 오퍼레이션의 최소 집합
    2. 구현방식으로 추상 오퍼레이션을 제공하는 방법

      • Adaptation 인터페이스를 추상 오퍼레이션으로 정의하고 상속받는 서브클래스는 추상 오퍼레이션에 대한 구현을 제공해야 하고 계층 구조를 갖는 객체를 Adaptation할 수 있다.
    3. Delegate 객체를 사용한다.(집합관계)

      • 자신에게 요청된 메시지를 다른 위임 개체에게 전달, 여러 가지 다른 Adaptation 전략을 수사할 수 있다.
      • 트리 구조를 계층적 디렉토리 구조로 Adaptation하는 위임자 역할 수행
    4.  파라미터화된 어댑터

      1. 어댑터의 파라미터화를 통하여 대체 가능한 어댑터를 만들 수 있다.

      2. 파라미터가 될 수 있는 블록 요소

        1. directoryDisplay := (TreeDisplay on: treeRoot) getChildrenBlock: [:node | node getSubdirectories] createGraphicNodeBlock: [:node | node createGraphicNode]

      3. 루비 코드

      1.  dirctoryDisplay = TreeDisplay.treeRoot;
      2. dirctoryDisplay.getChildrenBlockcreateGraphicNodeBlock({node| node.getSubdirectories},{node| node.createGraphicNode});

      인터페이스 Adaptation을 클래스로 만든다면 서브클래싱보다 더 편한 방법이다.

8) 관련 패턴

  • Bridge 패턴

    • 객체 어댑터와 클래스 구조가 유사하다
    • 사용 목적이 다르다
    • 구현과 추상 개념(인터페이스)를을 분리하여 서로 영향을 주지 않고 각각을 확장하려 하는 것
    • 어댑터는 존재하는 객체의 인터페이스를 변경
  • Decorator 패턴

    • 인터페이스 변경 없이도 객체에 새로운 행위를 추가할 수 있다.
    • 어댑터 보다는 애플리케이션을 위해 좋은 방법
    • 순수한 어댑터로는 불가능한 재귀적 합성이 가능


  • Proxy 패턴

    • 인터페이스를 변경하는 책임이 없다.
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 허혁

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 2008/03/29 09:52
    댓글 주소 수정/삭제 댓글
    lamda funtion은 얼마전에 haskell 스터디에서 배웠는데 바로 나오네. 역시 사람은 배워야 되는 듯.
  2. 2008/03/31 10:22
    댓글 주소 수정/삭제 댓글
    람다야 워낙 많이 쓰이는 개념이니깐.. ㅋㅋ

    믹스인이 C++에서도 구현가능하다는 것에 더 놀랐어..


BLOG main image
안녕하세요. 안정된 코딩, 여유로운 프로젝트, 떠오르는 코더 by 허혁

카테고리

분류 전체보기 (88)
direct (50)
indirect (21)
transmissive (10)
agenda (4)
idea (3)

달력

«   2008/07   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

최근에 달린 레몬펜 쪽지

Statistics Graph
Creative Commons License

이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이선스에 따라 이용하실 수 있습니다.