본문 바로가기

구조 디자인 패턴 - 복합체 본문

OOP 디자인 패턴/구조패턴

구조 디자인 패턴 - 복합체

개발자로 거듭나기 2023. 7. 6. 10:42
반응형

복합체 패턴 (Composite)

  • 복합체 패턴은 객체들을 트리 구조들로 구성한 후, 이러한 구조들과 개별 객체들처럼 작업할 수 있도록 하는 구조 패턴입니다.
  • 복합체 패턴은 앱의 핵심 모델이 트리로 표현될 수 있을 때만 사용하세요.

복합체 구성요소

  1. Component 추상클래스 : 트리의 단순 요소들과 복잡한 요소들 모두에 공통적인 작업을 설명합니다.
  2. Leaf 클래스 : 은 트리의 기본 요소이며 하위요소가 없습니다.
  3. Composite 클래스 : 컨테이너(일명 복합체)는 하위 요소들(잎 또는 기타 컨테이너)이 있는 요소입니다. 컨테이너는 자녀들의 구상 클래스들을 알지 못하며, 컴포넌트 인터페이스를 통해서만 모든 하위 요소들과 함께 작동합니다.
  4. 요청을 전달받으면 컨테이너는 작업을 하위 요소들에 위임하고 중간 결과들을 처리한 다음 최종 결과들을 클라이언트에 반환합니다.

요약

  • 복합체 패턴은 앱의 핵심 모델의 구조가 트리구조로 변환 될 수 있을 때 사용 할 수 있습니다.
  • 핵심모델을 잎새와 컨테이너(복합체)로 분리합니다. 컨테이너는 다른 더 작은 컨테이너나 잎새들을 포함할 수 있습니다.
  • 잎새와 컨테이너는 모두 컴포넌트라는 하나의 공통된 기준을 따라야 합니다.
  • 본문의 예에서 상자안의 상자와 물건에 대한 예시가 있는데, 여기서 물건이 잎새이고, 상자안의 상자와 최상위 상자등이 컨테이너에 해당합니다.
  • 또한, 물건의 총합을 구하는 과정은 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);

결과

출처

https://refactoring.guru/ko/design-patterns/composite

반응형

'OOP 디자인 패턴 > 구조패턴' 카테고리의 다른 글

구조디자인 패턴 - 브리지  (0) 2023.06.27
구조 디자인 패턴 - 어댑터  (0) 2023.06.10
Comments