본문 바로가기

Design Pattern/구조(Structural) 패턴

4. 컴포지트 패턴 (Composite Pattern)

목차

1. 컴포지트 패턴 (Composite Pattern) 이란?

2. 컴포지트 패턴 구조

3. 예제


컴포지트 패턴 (Composite Pattern) 이란?

 

컴포지트 패턴의 예시로 폴더와 파일이 있습니다.

폴더와 파일은 서로 다르지만 모두 폴더안에 넣을 수 있다는 공통점이 있습니다. 

 

이러한 공통점을 이용하여 사용자가 단일 객체와 복합 객체 모두 동일하게 다루도록 할 수 있게 도와주는

패턴이 컴포지트 패턴입니다.

 


 

컴포지트 패턴 구조

이름 내용
Item File 과 Folder 를 동일시하는 추상 클래스
Folder 폴더를 나타내는 클래스
File 파일을 나타내는 클래스
Main 메인 클래스

예제

 

Item 추상클래스

 

Item 추상클래스는 기본적인 것만제공하고 나머지는 Folder 와 File 클래스 에서 구현합니다.

먼저 name 을필드로 가지고 name을 얻을 수 있는 getName을 구현합니다.

 

getSize 메서드는 Folder 클래스와 File 클래스 각각 다르므로 abstract 로 남겨둡니다.

 

toString 은 기존에 있던 함수를 Override 하여 재구성합니다. 

 

public abstract class Item {

    private String name;
    
    public Item(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return name + "(" + getSize() + ")";
    }

    public abstract int getSize();
    
}

 

Folder 클래스

 

Item 추상클래스를 상속 받고 Item 추상클래스를 담을 수 있는 List를 필드로 가집니다.

 

생성자는 Item 추상클래스에서 필드로 지정해둔 name 을 넘겨줍니다.

 

getSize 메서드를 Override 하여 재구성해 줍니다.

 

마지막으로 add 와 list 메서드를 구현해 줍니다.

 

public class Folder extends Item {

    private LinkedList<Item> unitList = new LinkedList<>();

    public Folder(String name) {
        super(name);
    }

    @Override
    public int getSize() {
        int size = 0;
        Iterator<Item> it = unitList.iterator();

        while(it.hasNext()){
            Item unit = it.next();
            size += unit.getSize();
        }

        return size;
    }

    public boolean add(Item unit){
        unitList.add(unit);
        return true;
    }

    private void list(String indent, Item unit){
    	// Folder 와 File 을 구분하여 출력
    
        if(unit instanceof File){
            System.out.println(indent + unit);
        } else {
            Folder dir = (Folder) unit;
            Iterator<Item> it = dir.unitList.iterator();
            System.out.println(indent + "+ " + unit);
            
            while(it.hasNext()){
                list(indent + "   ", it.next());
            }
        }
    }

    public void list(){
        list("", this);
    }

}

 

 

File 클래스

 

Item 추상클래스를 상속받아 getSize 메서드를 구현해줍니다.

 

size 를 필드로 가지고 생성자를 통해 할당해 줍니다.

 

public class File extends Item {

    private int size;

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

    @Override
    public int getSize() {
        return size;
    }
    
}

 

 

Main 클래스

 

앞서 구현한 Folder 와 File을 생성해 줍니다.

public class Main {

    public static void main(String[] args) {
    
        Folder root = new Folder("root");
        root.add(new File("1.txt", 1000));
        root.add(new File("2.txt", 2000));

        Folder sub1 = new Folder("Folder1");
        root.add(sub1);
        sub1.add(new File("11.txt", 100));
        sub1.add(new File("12.txt", 4000));

        root.add(new File("끼어들기.txt", 1000));

        Folder sub2 = new Folder("Folder2");
        root.add(sub2);
        sub2.add(new File("21.txt", 250));
        sub2.add(new File("22.txt", 340));

        root.list();

    }
}

실행 결과

+ root(8690)
   1.txt(1000)
   2.txt(2000)
   + Folder1(4100)
      11.txt(100)
      12.txt(4000)
   끼어들기.txt(1000)
   + Folder2(590)
      21.txt(250)
      22.txt(340)