minstudio

컴포짓 패턴 (Composite)

컴포짓 패턴(Composite Pattern)은 객체들을 트리(Tree) 구조로 구성하여 개별 객체(단일 객체)와 복합 객체(그룹)를 클라이언트 입장에서 똑같은 방법으로 다룰 수 있게 해주는 패턴입니다.

가장 완벽한 예시는 파일 시스템입니다. 폴더 안에는 파일이 있을 수도 있고, 또 다른 폴더가 있을 수도 있습니다. 사용자가 폴더의 getSize()를 호출하면 폴더 안의 모든 파일과 하위 폴더의 크기를 재귀적으로 합산합니다. 파일이든 폴더든 똑같은 인터페이스(컴포넌트)로 취급하기 때문에 처리가 매우 단순해집니다.

🌳 Composite: 단일 객체와 복합 객체의 동일한 취급 << Component >> getSize() File (Leaf) 자신의 크기 반환 Folder (Composite) List<Component> children 자식들의 getSize() 합산 1:N 포함 관계 클라이언트는 이게 파일인지 폴더인지 구분할 필요 없이 무조건 getSize()만 부르면 끝!
<!-- ==========================================
// 📂 FileSystemComponent (공통 인터페이스)
// ==========================================

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

// 단일 객체(File)와 복합 객체(Folder)가 함께 구현할 공통 인터페이스
interface FileSystemComponent {
    String getName();
    int getSize();
    void print(String indent);
}

// ==========================================
// 📂 Leaf (가장 말단 노드 - 파일)
// ==========================================
class File implements FileSystemComponent {
    private String name;
    private int size;

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

    public String getName() { return name; }
    public int getSize() { return size; } // 파일은 자기 자신의 크기 반환
    
    public void print(String indent) {
        System.out.println(indent + "📄 " + name + " (" + size + "KB)");
    }
}

// ==========================================
// 📂 Composite (자식을 가지는 그룹 노드 - 폴더)
// ==========================================
class Folder implements FileSystemComponent {
    private String name;
    // 인터페이스(Component)의 리스트를 가지는 것이 핵심! (폴더든 파일이든 다 들어올 수 있음)
    private List<FileSystemComponent> children = new ArrayList<>();

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

    public void add(FileSystemComponent component) { children.add(component); }

    public String getName() { return name; }

    // 폴더의 크기는 재귀적으로 모든 자식들의 크기를 합산합니다.
    public int getSize() {
        int totalSize = 0;
        for (FileSystemComponent child : children) {
            totalSize += child.getSize(); // 파일이면 자기 크기, 폴더면 재귀 호출됨!
        }
        return totalSize;
    }

    public void print(String indent) {
        System.out.println(indent + "📁 " + name + " (총 " + getSize() + "KB)");
        for (FileSystemComponent child : children) {
            child.print(indent + "  ");
        }
    }
}

// ==========================================
// 📂 Main.java (사용 예시)
// ==========================================
public class Main {
    public static void main(String[] args) {
        Folder root = new Folder("C:");
        Folder dev = new Folder("Dev");
        Folder docs = new Folder("Docs");

        File resume = new File("이력서.pdf", 1024);
        File code = new File("Main.java", 15);
        File db = new File("oracle.sql", 5000);

        docs.add(resume);
        dev.add(code);
        dev.add(db);
        
        root.add(docs);
        root.add(dev);

        // root 폴더를 출력하라고 하면, 하위 폴더와 파일의 처리가 연쇄적으로(재귀적으로) 일어납니다.
        root.print("");
    }
}
컴포짓 패턴 (Composite) | Minstudio