본문 바로가기

Domain/디자인패턴

[디자인패턴] 컴포지트 패턴(Composite Pattern)

컴포지트 패턴(Composite Pattern)

컴포지트 패턴이란 객체들의 관계를 트리 구조로 구성하여 전체-부분의 관계 계층을 표현하는 패턴으로, 사용자가 단일 객체와 복합 객체 모두 동일한 인터페이스로 다룰 수 있다. 말이 어렵지만 대표적인 예시를 들면 디렉토리, 파일 구조와 같다. 디렉토리는 '복합 객체'이며 파일은 '단일 객체'이다. 사용자인 OS 유저는 디렉토리, 파일에 대해 삭제/이름 바꾸기 등의 작업을 동일한 인터페이스로 수행할 수 있다.

  • Component: 구체적인 부분
  • Leaf: 부분 클래스(단일 객체)로 Composite의 일부가 될 수 있다.
  • Composite: 복합 객체로 복수 개의 Component를 가질 수 있다. 즉, Component를 상속받아 구현한 Leaf와 Composite를 모두 가질 수 있다.

예제. 디렉토리-파일 구조

//Component
interface FileSystem{
    fun getSize():Int
    fun remove()
}

//Leaf
class File(
    private val name: String,
    private val size: Int,
) : FileSystem{
    override fun getSize():Int{
        return size
    }
    override fun remove():Int{
         println("$name 파일 삭제")
    }
}

//Composite
class Directory(
    private val name: String,
    private val components : ArrayList<FileSystem> = ArrayList(),
) : FileSystem{
    override fun getSize():Int{
    	var total = 0
        for(component in components)
        	total=component.getSize()
        return total
    }
    override fun remove():Int{
         for(component in components)
        	component.remove()
         println("$name 디렉토리 삭제")
    }
    
    fun add(fileSystem:FileSystem){
    	components.add(fileSystem)
    }
}

FileSystem을 상속받는 파일과 디렉토리가 존재한다. 디렉토리 내부에는 여러 개의 컴포넌트(파일시스템;파일, 디렉토리)가 존재할 수 있다. 파일과 디렉토리 모두 getSize(), remove() 메소드로 관리가 가능하다. 즉, 동일한 인터페이스로 작업을 수행할 수 있다.

 

참고

  • 얄팍한 코딩사전 - 객체지향 디자인패턴 2