패턴
: 복합체(Composite)
의도
: 부분과 전체의 계층을 표현하기 위해 객체들을 모아 트리 구조로 구성한다. 사용자로 하여금 개별 객체와 복합 객체를 모두 동일하게 다룰 수 있도록 하는 패턴이다.
동기
: 그래픽 편집기나 구조도 캡쳐 시트템 같은 그래픽 응용프로그램을 살펴보면, 사용자가 간단한 그림 구성요들을 모아서 복잡한 다이어그램을 생성할 수 있게 한다. 사용자는 더 큰 그림 요소를 만글기 위해 구성요소들을 그룹으로 만들고,
이 그룹이 다 더큰 그룹을 형성하기도 한다.
이는 마이크로소프트의 파워포인트의 그룹 기능을 생각하면 이해하기 쉽다.
출처 : http://blog.naver.com/gamediz/20042595126
: 1번은 A, B, C, D라는 객체를 놓았다.
: 2번은 B객체를 늘렸다. 객체 하나에 대한 컨트롤이다.
: 3번은 A, B, C, D 그룹화 해서 한 방향으로 늘렸다.
: 4번은 B, C, D를 그룹화 하여 한 방향으로 늘리고 A는 단일객체로 남겨두었다.
활용성
: 부분 - 전체의 객체 계통을 표현하고 싶을 때.
: 사용자가 객체의 합성으로 생긴 복합 객체와 개개의 객체 사이의 차이를 알지 않고도, 자기 일을 할 수 있도록 만들고 싶을 때, 사용자는 복합 구조(composite structure)의 모든 객ㅊ를 똑같이 취급하게 된다.
구조도
결과
: 기본 객체와 복합 객ㅊ로 구성된 하느이 일관된 클래스 계통을 정의한다.
: 사용자 코드가 단순해 진다.
: 새로운 종류의 구성 요소를 쉽게 추가할 수 있다.
: 설계가 지나치게 범용성을 많이 가진다.
예제
컴퓨터는 스테레오 부품들처럼 다양한 장비들을 포함하는 객체로, 컴퓨터와 장비 객체 간의 부분 - 전체 관계가 성립한다. 본체는 드라이브와 평명 보드를 포함하고, 버스는 카드를, 캐비닛은 덮개와 버스를 포함하는 예제인데, 이런 구조는 복합체 패턴이라 할 수 있다.
1. Equipment 클래스로 집합 관계에서 포함되는 장비 객체들에 대한 인터페이스를 정의 한다.
class Equipment
{
public :
virtual ~Equipment();
const char* Name() { return _name; ; }
virtual Watt Power(); virtual Currency NetPrice(); virtual Currency Discountrice();
virtual void Add(Equipment*);
virtual void Remove(Equipment*);
virtual Iterator<Equipment*>* CreateIerator();
protected : Equipment(const char*);
private :
const char* _name;
};
- Equipment 클래스는 장비의 가격을 반환하는 데 필요한 연산(NetPrice(), DiscountPrice())들에 대한 인터페이스를
정의하고, 이를 상속받는 서브클래스는 인터페이스에 대한 실제 구현을 정의하여, 특정 장비에 대한 가격을 반환한다.
- Equipmnet 클래스는 CreateIterator()연산을 선언하여 자신이 포함하는 요소를 접근,관리하는 데 필요한 Irerator를
만들어 반환하도록 정의합니다. 기본 구현은 공집합을 순환하는 Iterator인 Null - Iterator를 반환한다.
2. Equipmnet의 서브 클래스에는 디스크 드라이브, 집적 회로, 스위치 등을 나타내는 말단 클래스들이 포함될 것이다.
class FloppyDist : public Equipment
{
public :
FloppyDist(const char*);
virtual ~FloppyDist();
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency Discountrice();
};
3. Equipment를 동일하게 상속받으면서 무엇인가를 포함할 수 있는 복합 객체를 CompositeEquipment로 정의하였다.
class CompositeEquipment : public Equipment
{
public :
virtual ~CompositeEquipment();
virtual Watt Power(); virtual Currency NetPrice(); virtual Currency Discountrice();
virtual void Add(Equipment*);
virtual void Remove(Equipment*);
virtual Iterator<Equipment*>* CreateIerator();
protected : CompositeEquipment(const char*);
private :
List<Equipment*> _equipment;
}
- CompositeEquipment는 Equipment에 정의된 인터페이스에 대한 실제 구현을 제공하며, 복합 객체이므로
CompositeEquipment는 자신이 포함하는 복합 부분들을 관리하는 연산을 정의합니다. 즉, Add(), Remove()는 장비
리스트에 장비를 추가 삭제하는 연산이며, CreateIterator() 연산은 이 리스트를 순회하는 iterator를 반환한다.
4. 업무 처리 연산 중 하나인 NetPrice의 구현을 보면, CreateIterator를 사용하여 자신이 포함하는 각 구성요소를 구하고
이 구성요소 객체에 다시 NetPrice()매서드를 호출하여 각 구성요소의 값을 구한 후 이 값들을 합산하여 전ㅊ 가격을
구하고 있다.
Currency CompositeEquipment::NetPrice()
{
Iterator<Equipment*>* i = CreateIerator(); Currency total = 0;
for( i->First(); !->IsDone(); i->Next()
{
total += i->CurrentItem()->NetPrice();
}
delete i;
return total;
}
5. 이제는 컴퓨터 새시를 CompositeEquipment의 서브 클래스인 Chassis로 나타 낼 수 있다. Chassis는 자식 관련 연산을 모두 CompositeEquipment에서 물려 받습니다.
class Chassis : public CompositeEquipment
{
public :
Chassis(const char*);
virtual ~Chassis();
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency Discountrice();
};
6. Cabinet과 Bus는 Chassis 클래스와 동일한 방법으로 복합 객체의 특성을 갖도록 정의한다. 컴퓨터 조립에 필요한 장치는 다 모인 셈이다.
Cabinet *cabinet = new Cabinet("PC Cabinet"); Chassis *chassis = new Chassis("PC Chassis");
cabinet->Add(chassis);
Bus* bus = new Bus("MCA Bus");
bus->Add(new Card("16Mbs Token Ring"));
chassis->Add(bus);
chassis->Add(new FloppyDist("3.5bin Floppy"));
cout << "The net price is " << chassis->NetPrice() << endl;
끝.-
'Design Pattern' 카테고리의 다른 글
[Design pattern] DECORATOR (0) | 2013.02.25 |
---|---|
[Design pattern] 반복자 Iterator (0) | 2013.02.25 |
[Design pattern] 감시자 Observer (0) | 2013.02.25 |
[Design pattern] Bridge (0) | 2013.02.21 |
[Design pattern] Reflection (0) | 2013.02.21 |