Structural Patterns(구조 패턴) :: Composite(복합체)
구분
객체 구조 (Object Structural)
의도
- 부분과 전체의 계층을 표현하기 위해 객체들을 모아 트리 구조로 구성한다. 사용자로 하여금 개별 객체와 복합 객체를 모두 동일하게 다룰 수 있도록 하는 패턴이다.
포인트
- 기본 클래스와 이들의 컨테이너를 모두 표현할 수 있는 하나의 추상화 클래스를 정의하는 것
사용시기
- 부분-전체의 객체 계통을 표현하고 싶을 때
- 사용자가 객체의 합성으로 생긴 복합 객체와 개객의 객체 사이의 차이를 알지 않고도 자기 일을 할 수 있도록 만들고 싶을 때, 사용자는 복합 구조(Composite Structure)의 모든 객체를 똑같이 취급하게 된다.
장점과 단점
- 기본 객체와 복합 객체로 구성된 하나의 일관된 클래스 계통을 정의한다. 기본 객체는 더 복합적인 객체들에 속해 있을 수 있다. 물론 이 복합 객체 역시 다른 것에 속해 있는 것일 수 있다. 그러나 사용자 코드는 일반화된 상위 개념의 객체를 조작하는 방식으로 프로그래밍하면, 런타임 기본 객체와 복합 객체를 구분하지 않고 일관되게 프로그래밍할 수 있게 된다.
- 사용자의 코드가 단순해진다. 사용자 코드는 복합 구조이나 단일 객체와 동일하게 다루는 코드로 작성되기 때문이다. 즉, 사용자는 객체의 특성이 복합 구조인지 단일 구조인지조차 모르고 개발할 수 있다. 이런 구분이 필요치 않으므로 개발자의 코드에 "꼬리표-case-문장" 스타일의 함수를 쓸 필요가 없어지므로 코드가 단순해진다.
- 새로운 종류의 구성요소를 쉽게 추가할 수 있다. 새롭게 정의된 Composite나 Leaf의 서브클래스들은 기존에 존재하는 구조들과 독립적으로 동작이 가능하게 된다. 그러므로 새로운 요소가 추가되었다고 해서 사용자의 프로그램이 변경될 필요는 전혀 없다.
- 설계가 지나치게 범용성을 많이 가진다. 새로운 요소를 쉽게 추가할 때의 단점은 복합체의 구성요소에 제약을 가하기 힘들다는 것이다. 가끔 복합체가 오직 한 개의 구성요소만 가졌으면 할 때가 있다. Composite클래스만으로 타입 시스템을 통해 이런 제약을 가할 수 없다. 런타임 점검이 들어가야 한다.
구현의 유의점
1. 포함 객체에 대한 명확한 참조자
2. 구성요소 공유
3. Component 인터페이스를 최대화
4. 자식을 관리하는 연산 선언
5. 컴포넌트가 컴포넌트의 리스트를 구현할 수 있을까?
6. 자식 사이의 순서 정하기
7. 성능 개선을 위한 캐싱(Caching)
8. 누가 구성요소를 삭제하는 책임을 질까?
9. 구성요소를 저장하기 위해 가장 적당한 데이터 구조는?
관련 패턴
구성요소-부모 간의 연결은 책임 연쇄 패턴에서 많이 사용되는 예이다.
장식자 패턴은 자주 복합체 패턴과 함께 사용된다. 이 두 패턴이 함께 사용될 때는 둘 다 동일한 하나의 부모 클래스를 상속받게 된다, 따라서 장식자는 Add(), Remove(), GetChild()와 같은 연산을 통해서 Component의 인터페이스를 지원해야 한다.
플라이급 패턴으로 구성요소의 공유 방법을 얻을 수 있다. 단, 공유되는 구성요소의 보무는 참조할 수 없다.
반복자 패턴을 이용하면, 구성요소를 순회하는 방법을 얻을 수 있다.
방문자 패턴을 이용하면, 이 패턴을 사용하지 않을 때 Composite와 Leaf클래스에 걸쳐 분산될 수 있는 행동을 국소화시킬 수 있다.
참조문헌
- GoF의 디자인패턴
2016년 2월 26일 금요일
2016년 2월 24일 수요일
GoF의 디자인 패턴 - Adapter
Structural Patterns(구조 패턴) :: Adapter(적응자)
구분
클래스, 객체 구조 (Class, Object Structural)
의도
- 클래스의 인터페이스를 사용자가 기대하는 인터페이스 형태로 적응(변환)시킨다. 서로 일치하지 않는 인터페이스를 갖는 클래스들을 함께 동작시킨다.
다른이름
- 래퍼(Wrapper)
사용시기
- 기존 클래스를 사용하고 싶은데 인터페이스가 맞지 않을 때
- 아직 예측하지 못한 클래스나 실제 관련되지 않는 클래스들이 기존 클래스를 재사용하고자 하지만, 이미 정의된 재사용 가능한 클래스가 지금 요청하는 인터페이스를 꼭 정의하고 있지 않을 때, 다시 말해, 이미 만든 것을 재사용하고자 하나 이 재사용 가능한 라이브러리를 수정할 수 없을 때
- [객체 적응자(object adapter)만 해당] 이미 존재하는 여러 개의 서브클래스를 사용해야 하는데, 이 서브클래스들의 상속을 통해서 이들의 인터페이스를 다 개조한다는 것이 현실성이 없을 때, 객체 적응자를 써서 부모 클래스의 인터페이스를 변형하는 것이 더 바람직함.
장점과 단점
1. 클래스 적응자(Class Adapter)
- Adapter클래스는 Adaptee클래스를 Target클래스로 변형하는데, 이를 위해서 Adaptee클래스를 상속받아야 하기 때문에, 하나의 클래스와 이 클래스의 모든 서브클래스들을 개조할 때라면 클래스 적응자 방식을 사용할 수 없다. 즉, Adapter는 명시적으로 Adaptee를 상속받고 있을 뿐 Adaptee의 서브클래스들을 상속받는 것은 아니므로, Adaptee의 서브클래스에 정의된 기능들을 사용할 수 없다.
- Adapter클래스는 Adaptee클래스를 상속하기 때문에 Adaptee에 정의된 행동을 재정의할 수도 있다.
- 한 개의 객체(Adapter)만 사용하며, Adaptee로 가기 위한 추가적인 포인터 간접화는 필요하지 않다.
2. 객체 적응자(Object Adapter)
- Adapter클래스는 하나만 존재해도 수 많은 Adaptee클래스들과 동작할 수 있다. 왜냐하면 Adapter객체가 포함하는 Adaptee에 대한 참조자는 Adaptee의 인스턴스를 관리할 수도 있고, Adaptee 클래스를 상속받는 다른 서브클래스들의 인스턴스도 관리할 수 있기 때문이다. 그러므로 하나의 Adapter클래스로 모든 Adaptee클래스와 이를 상속받는 서브클래스 모두를 이용할 수 있게 된다.
- Adaptee클래스의 행동을 재정의하기가 매우 어렵다. 이것을 위해서는 Adaptee클래스를 상속받아서 새로운 서브클래스를 만들고 Adapter클래스는 Adaptee클래스가 아닌 Adaptee클래스의 해당 서브클래스를 참조하도록 해야 한다.
구현의 유의점
1. Adapter클래스가 실제 적응 작업을 위해 들여하는 작업은 얼마나 되나?
2. 대체 가능(Pluggable) 적응자 - 위임을 사용하자
관련 패턴
Bridge패턴은 Object Adapter와 클래스 구조가 유사하나 그 사용 목적이 다르다.
Bridge패턴은 서로 다른 구현이 만족할 추상 개념을 분리하여 서로에게 영향을 주지 않고 각각 확장할 수 있도록 하려는 것이고, Adapter패턴은 존재하는 객체의 인터페이스를 변경하려는 것이다.
참조문헌
- GoF의 디자인패턴
구분
클래스, 객체 구조 (Class, Object Structural)
의도
- 클래스의 인터페이스를 사용자가 기대하는 인터페이스 형태로 적응(변환)시킨다. 서로 일치하지 않는 인터페이스를 갖는 클래스들을 함께 동작시킨다.
다른이름
- 래퍼(Wrapper)
사용시기
- 기존 클래스를 사용하고 싶은데 인터페이스가 맞지 않을 때
- 아직 예측하지 못한 클래스나 실제 관련되지 않는 클래스들이 기존 클래스를 재사용하고자 하지만, 이미 정의된 재사용 가능한 클래스가 지금 요청하는 인터페이스를 꼭 정의하고 있지 않을 때, 다시 말해, 이미 만든 것을 재사용하고자 하나 이 재사용 가능한 라이브러리를 수정할 수 없을 때
- [객체 적응자(object adapter)만 해당] 이미 존재하는 여러 개의 서브클래스를 사용해야 하는데, 이 서브클래스들의 상속을 통해서 이들의 인터페이스를 다 개조한다는 것이 현실성이 없을 때, 객체 적응자를 써서 부모 클래스의 인터페이스를 변형하는 것이 더 바람직함.
장점과 단점
1. 클래스 적응자(Class Adapter)
- Adapter클래스는 Adaptee클래스를 Target클래스로 변형하는데, 이를 위해서 Adaptee클래스를 상속받아야 하기 때문에, 하나의 클래스와 이 클래스의 모든 서브클래스들을 개조할 때라면 클래스 적응자 방식을 사용할 수 없다. 즉, Adapter는 명시적으로 Adaptee를 상속받고 있을 뿐 Adaptee의 서브클래스들을 상속받는 것은 아니므로, Adaptee의 서브클래스에 정의된 기능들을 사용할 수 없다.
- Adapter클래스는 Adaptee클래스를 상속하기 때문에 Adaptee에 정의된 행동을 재정의할 수도 있다.
- 한 개의 객체(Adapter)만 사용하며, Adaptee로 가기 위한 추가적인 포인터 간접화는 필요하지 않다.
2. 객체 적응자(Object Adapter)
- Adapter클래스는 하나만 존재해도 수 많은 Adaptee클래스들과 동작할 수 있다. 왜냐하면 Adapter객체가 포함하는 Adaptee에 대한 참조자는 Adaptee의 인스턴스를 관리할 수도 있고, Adaptee 클래스를 상속받는 다른 서브클래스들의 인스턴스도 관리할 수 있기 때문이다. 그러므로 하나의 Adapter클래스로 모든 Adaptee클래스와 이를 상속받는 서브클래스 모두를 이용할 수 있게 된다.
- Adaptee클래스의 행동을 재정의하기가 매우 어렵다. 이것을 위해서는 Adaptee클래스를 상속받아서 새로운 서브클래스를 만들고 Adapter클래스는 Adaptee클래스가 아닌 Adaptee클래스의 해당 서브클래스를 참조하도록 해야 한다.
구현의 유의점
1. Adapter클래스가 실제 적응 작업을 위해 들여하는 작업은 얼마나 되나?
2. 대체 가능(Pluggable) 적응자 - 위임을 사용하자
관련 패턴
Bridge패턴은 Object Adapter와 클래스 구조가 유사하나 그 사용 목적이 다르다.
Bridge패턴은 서로 다른 구현이 만족할 추상 개념을 분리하여 서로에게 영향을 주지 않고 각각 확장할 수 있도록 하려는 것이고, Adapter패턴은 존재하는 객체의 인터페이스를 변경하려는 것이다.
참조문헌
- GoF의 디자인패턴
GoF의 디자인 패턴 - Structural Patterns
Structural Patterns(구조 패턴)
의도
- 인터페이스나 구현을 복합하는 것이 아니라 새로운 기능을 실현하기 위해 객체를 합성하는 방법을 제공한다.
참조문헌
- GoF의 디자인패턴
의도
- 인터페이스나 구현을 복합하는 것이 아니라 새로운 기능을 실현하기 위해 객체를 합성하는 방법을 제공한다.
참조문헌
- GoF의 디자인패턴
2016년 2월 15일 월요일
GoF의 디자인 패턴
1. Creational Patterns(생성 패턴)
- Abstract Factory(추상 팩토리)
- Builder(빌더)
- Factory Method(팩토리 메서드)
- Prototype(원형)
- Singleton(단일체)
2. Structural Patterns(구조 패턴)
- Adapter(적응자)
- Bridge(가교)
- Composite(복합체)
- Decorator(장식자)
- Facade(퍼사드)
- Flyweight(플라이급)
- Proxy(프록시)
3. Behavioral Patterns(행동 패턴)
- Chain of Responsibility(책임 연쇄)
- Command(명령)
- Interpreter(해석자)
- Iterator(반복자)
- Mediator(중재자)
- Memento(메멘토)
- Observer(감시자)
- State(상태)
- Strategy(전략)
- Template Method(템플릿 메서드)
- Visitor(방문자)
총 23개의 디자인 패턴.... 하나씩 풀어보자. 실전에 적용해보며~
참조문헌
- GoF의 디자인패턴
피드 구독하기:
글 (Atom)