구조 디자인 패턴 - 복합체 본문
반응형
복합체 패턴 (Composite)
- 복합체 패턴은 객체들을 트리 구조들로 구성한 후, 이러한 구조들과 개별 객체들처럼 작업할 수 있도록 하는 구조 패턴입니다.
- 복합체 패턴은 앱의 핵심 모델이 트리로 표현될 수 있을 때만 사용하세요.
복합체 구성요소
- Component 추상클래스 : 트리의 단순 요소들과 복잡한 요소들 모두에 공통적인 작업을 설명합니다.
- Leaf 클래스 : 잎은 트리의 기본 요소이며 하위요소가 없습니다.
- Composite 클래스 : 컨테이너(일명 복합체)는 하위 요소들(잎 또는 기타 컨테이너)이 있는 요소입니다. 컨테이너는 자녀들의 구상 클래스들을 알지 못하며, 컴포넌트 인터페이스를 통해서만 모든 하위 요소들과 함께 작동합니다.
- 요청을 전달받으면 컨테이너는 작업을 하위 요소들에 위임하고 중간 결과들을 처리한 다음 최종 결과들을 클라이언트에 반환합니다.
요약
- 복합체 패턴은 앱의 핵심 모델의 구조가 트리구조로 변환 될 수 있을 때 사용 할 수 있습니다.
- 핵심모델을 잎새와 컨테이너(복합체)로 분리합니다. 컨테이너는 다른 더 작은 컨테이너나 잎새들을 포함할 수 있습니다.
- 잎새와 컨테이너는 모두 컴포넌트라는 하나의 공통된 기준을 따라야 합니다.
- 본문의 예에서 상자안의 상자와 물건에 대한 예시가 있는데, 여기서 물건이 잎새이고, 상자안의 상자와 최상위 상자등이 컨테이너에 해당합니다.
- 또한, 물건의 총합을 구하는 과정은 operation에 해당하게 됩니다. 컨테이너에서는 본인 하위에 있는 잎새노드들을 재귀적으로 순회하면서 값을 계산하게 됩니다.
- 이로써 operation을 수행하는 동안 잎새노드인지 컨테이너인지 알 필요 없이, 재귀적으로 내려가면서 합을 계산하게 됩니다.
코드
abstract class Component {
protected parent!: Component | null;
public setParent(parent: Component | null) {
this.parent = parent;
}
public getParent(): Component | null {
return this.parent;
}
public add(component: Component): void { }
public remove(component: Component): void { }
public isComposite(): boolean {
return false;
}
public abstract compositeOperation(): string;
}
class Leaf extends Component {
public compositeOperation(): string {
return 'Leaf';
}
}
class Composite extends Component {
protected children: Component[] = [];
public add(component: Component): void {
// 컴포넌트 추가 (브랜치가 될 수 있고, 잎이 될 수 있다.)
this.children.push(component);
// 추가를 하면 현재 Composite 클래스 밑으로 들어오게 된다.
component.setParent(this);
}
public remove(component: Component): void {
const componentIndex = this.children.indexOf(component);
this.children.splice(componentIndex, 1);
// 관계 해제
component.setParent(null);
}
// 복합체인가?
public isComposite(): boolean {
return true;
}
// 브랜치들 +로 연결
public compositeOperation(): string {
const results = [];
for (const child of this.children) {
// 재귀적으로 children 배열 안에 자식들의 compositeOperation를 수행한다.
results.push(child.compositeOperation());
}
return `Branch(${results.join('+')})`;
}
}
function clientCode(component: Component) {
console.log(`RESULT: ${component.compositeOperation()}`);
}
// 단순한 컴포넌트(잎새) 에서는 단순히 그 동작만 수행하게 된다.
const simpleComponent = new Leaf();
clientCode(simpleComponent);
console.log('');
// 트리가 있고
const tree = new Composite();
// 그 밑에 브랜치1,2가 있는 상황
const branch1 = new Composite();
// 브랜치1에는 자식노드 2개 추가
branch1.add(new Leaf());
branch1.add(new Leaf());
const branch2 = new Composite();
// 브랜치2에는 자식노드 1개 추가
branch2.add(new Leaf());
// 그 후 트리에 브랜치1,2 추가
tree.add(branch1);
tree.add(branch2);
clientCode(tree);
console.log('');
// 트리에 자식추가
function clientCode2(component1: Component, component2: Component) {
if (component1.isComposite()) {
component1.add(component2);
}
// 트리순회
console.log(`RESULT: ${component1.compositeOperation()}`);
}
// tree에 simpleComponent 추가
clientCode2(tree, simpleComponent);
결과
출처
반응형
'OOP 디자인 패턴 > 구조패턴' 카테고리의 다른 글
구조디자인 패턴 - 브리지 (0) | 2023.06.27 |
---|---|
구조 디자인 패턴 - 어댑터 (0) | 2023.06.10 |
Comments