Gof의 디자인 패턴 -복합체 패턴

Groot·2023년 12월 10일
0

TIL

목록 보기
139/153
post-thumbnail
post-custom-banner

복합체 패턴

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

활용성

  • 부분 - 전체의 객체 계통을 표현하고 싶을 때
  • 사용자가 객체의 합성으로 생긴 복합 객체와 개개의 객체 사이의 차이를 알지않고도 자기 일을 할 수 있도록 만들고 싶을 때

구조

요소

  • 컴포넌트(Component)
    • 집합 관계에 정의될 모든 객체에 대한 인터페이스를 정의
  • 리프(Leaf)
    • 가장 말단의 객체, 즉 자식이 없는 객체, 인터페이스 구현
  • 컴포지트(Composite)
    • 자식이 있는 구성요소에 대한 행동을 정의, 자신이 복합하는 요소들을 저장하면서 인터페이스에 정의된 자식 관련 연산을 구현
  • 클라이언트(Client)
    • 인터페이스를 통해 복합 구조 내의 객체들을 조작

협력 방법

  • 사용자는 Component 인터페이스를 사용한다
  • 요청받은 대상이 Leaf 인스턴스면 자신이 정의한 행동을 직접 수행한다.
  • 대상이 Composite이면 자식 객체들에게 요청을 위임한다.

장점

  • 사용자의 코드가 단순해짐.
    • 코드가 복합 구조이나 단일 객체와 동일하게 다루는 코드로 작성되기 때문에.(사용자는 복합구조인지 단일구조인지 모르기 때문)
  • 개방폐쇄 원칙.
    • 객체 트리와 작동하는 기존 코드를 훼손하지 않고 앱에 새로운 요소 유형들을 도입

단점

  • 기능이 너무 다른 클래스들에는 공통 인터페이스를 제공하기 어려울 수 있으며, 어떤 경우에는 컴포넌트 인터페이스를 과도하게 일반화해야 하여 이해하기 어렵게 만들 수 있다.

예시 코드

protocol FileComponent {
    func display()
    func add(file: FileComponent)
}

extension FileComponent {
    func add(file: FileComponent) { }
}

class File: FileComponent {
    private var name: String

    init(name: String) {
        self.name = name
    }

    func display() {
        print("File: \(name)")
    }
}

class Directory: FileComponent {
    private var name: String
    private var files: [FileComponent] = []

    init(name: String) {
        self.name = name
    }

    func add(file: FileComponent) {
        files.append(file)
    }

    func display() {
        print("Directory: \(name)")
        for file in files {
            file.display()
        }
    }
}

let file1: FileComponent = File(name: "file1.txt")
let file2: FileComponent = File(name: "file2.txt")
let directory1: FileComponent = Directory(name: "Folder 1")

directory1.add(file: file1)
directory1.add(file: file2)

let file3: FileComponent = File(name: "file3.txt")
let directory2: FileComponent = Directory(name: "Folder 2")

directory2.add(file: file3)

let rootDirectory: FileComponent = Directory(name: "Root")
rootDirectory.add(file: directory1)
rootDirectory.add(file: directory2)

// 모든 파일 및 디렉터리를 표시
rootDirectory.display()

참고

profile
I Am Groot
post-custom-banner

0개의 댓글