Design Pattern/구조(Structural) 패턴

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

파도솔레라미시 2023. 10. 30. 22:22

목차

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)