Design Pattern

Design Pattern | 컴포지트 패턴(Composite Pattern)

이진유진 2024. 2. 22. 19:18
반응형
오늘은 디자인 패턴 스터디 두번째 항목인 컴포지트 패턴에 대해 알아보도록 하겠습니다. 

 

 

컴포지트 패턴(Composite Pattern)

객체 지향 디자인 패턴 중 하나로, 복합 객체를 구성하는 개별적인 객체들을 모두 동일한 방법으로 다룰 수 있게 하는 패턴입니다. 

이 패턴은 개별 객체와 복합 객체(그룹화된 객체)를 동일하게 다룰 수 있도록 하여 클라이언트 코드가 객체 계층 구조를 일관되게 처리할 수 있도록 도와줍니다.

 

컴포지트 패턴은 트리 구조를 가진 객체들을 다루는데 유용합니다. 

 

간단한 예시로, 파일 시스템을 생각해볼 수 있습니다.

파일 시스템에서 디렉터리와 파일을 구성하는 것과 같이, 여러개의 객체가 포함된 복합 객체를 처리할 때 이용할 수 있습니다. 

 

이러한 패턴을 사용하는 이유는, 

코드가 많으면, 코드의 복잡도가 상승하고, 그에따라 에러가 발생할 확률이 높아집니다. 

컴포지트 패턴을 사용하게되면, 개별 객체와 복합 객체를 동일한 인터페이스로 다룰 수 있는데, 

개별 객체는 단순히 자기 자신을 다루는 방법으로 처리되고, 

복합객체는 자신에게 속한 개별 객체를 재귀적으로 다룰 수 있습니다. 

이렇게하면, 클라이언트는 개별 객체와 복합 객체를 구분하지 않고 동일한 방식으로 사용할 수 있다는 장점을 가집니다. 

 

파일과 디렉터리는 각각 단일 객체와 복합 객체에 해당합니다. 파일과 디렉터리 모두 공통된 인터페이스를 가지며,

디렉터리 안에는 또 다른 파일이나 디렉터리를 포함할 수 있습니다.

 

이러한 패턴의 장점 중 하나는 클라이언트 코드가 객체의 구체적인 타입을 몰라도 되며,

일관된 방식으로 상호작용할 수 있다는 것입니다.

객체의 계층 구조가 변경되어도 클라이언트 코드에는 영향을 주지 않고 사용이 가능하므로 유연성이 향상됩니다.

 
 
import java.util.ArrayList;
import java.util.List;

// Component 인터페이스
interface Component {
    void display();
}

/*
Component는 Leaf 객체와 Composite 객체가 공통적으로 가져야 하는 메서드를 정의하는 인터페이스입니다.
*/

// Leaf 객체: File 클래스
class File implements Component {
    private String name;

    public File(String name) {
        this.name = name;
    }

    @Override
    public void display() {
        System.out.println("File: " + name);
    }
}

/*
File 클래스는 Leaf 객체로, 파일을 나타냅니다.
파일의 이름을 저장하고, display 메서드를 구현하여 파일 정보를 출력합니다.
*/

// Composite 객체: Directory 클래스
class Directory implements Component {
    private String name;
    private List<Component> components = new ArrayList<>();

    public Directory(String name) {
        this.name = name;
    }

    public void addComponent(Component component) {
        components.add(component);
    }

    @Override
    public void display() {
        System.out.println("Directory: " + name);
        for (Component component : components) {
            component.display();
        }
    }
}

/*
Directory 클래스는 Composite 객체로, 디렉터리를 나타냅니다.
디렉터리의 이름을 저장하고, 하위에 속한 컴포넌트들을 저장하는 List<Component> components를 가지고 있습니다.
addComponent 메서드를 통해 컴포넌트(파일 또는 디렉터리)를 추가할 수 있습니다.
display 메서드는 현재 디렉터리 정보를 출력하고, 속한 각 컴포넌트의 display 메서드를 호출하여 하위 구조를 출력합니다.
*/

// 클라이언트 코드
public class CompositePatternExample {
    public static void main(String[] args) {
        // 파일 생성
        File file1 = new File("File 1");
        File file2 = new File("File 2");

        // 디렉터리 생성
        Directory dir1 = new Directory("Directory 1");
        Directory dir2 = new Directory("Directory 2");

        // 디렉터리에 파일 추가
        dir1.addComponent(file1);
        dir2.addComponent(file2);

        // 또 다른 디렉터리 생성
        Directory dir3 = new Directory("Directory 3");

        // 두 번째 디렉터리에 첫 번째 디렉터리와 또 다른 디렉터리 추가
        dir2.addComponent(dir1);
        dir2.addComponent(dir3);

        // 전체 구조 출력
        dir2.display();
    }
}

/*
main 메서드에서는 간단한 파일 시스템을 생성하고 출력하는 예시를 보여줍니다.
File 객체 두 개와 Directory 객체 세 개를 생성하여 조합합니다.
마지막으로 두 번째 디렉터리의 display 메서드를 호출하여 전체 파일 시스템 구조를 출력합니다.
*/
 

코드 실행결과

Directory: Directory 2
File: File 2
Directory: Directory 1
File: File 1
Directory: Directory 3

 

 

출처 : https://jangjjolkit.tistory.com/60

 

컴포지트 패턴은 개별 객체와 복합 객체 처리 방법이 같을 때, 

전체 - 부분 관계로 정의할 수 있습니다. 

객체의 구조가 복잡할 때 유용하며, 

객체 간의 결합도를 낮추어 유연성을 높일 수 있고, 

새로운 개별 객체나 복합 객체를 추가하더라도 클라이언트 코드를 수정할 필요가 없어 유지보수에 좋습니다. 

 

 

 

 

참고문헌

https://jangjjolkit.tistory.com/60

https://mygumi.tistory.com/343

https://en.wikipedia.org/wiki/Composite_pattern

반응형