Design Pattern/구조 패턴

Composite Pattern

 

컴포지트 패턴(Composite pattern)이란 객체들의 관계를 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴으로, 사용자가 단일 객체와 복합 객체 모두 동일하게 다루도록 한다.

객체 그룹과 하나의 객체가 동일한 행위를 할때 적용, 트리구조를 생성할 때 사용될 수 있다.

 

예시는 파일 시스템으로

 

1. Component

Node라는 Component를 구성합니다.

(equals와 hashcode는 Directory에서 remove시 객체의 내용이 같다면 삭제 되도록 하기 위해서 재정의 하였습니다.)

import java.util.Objects;

public abstract class Node {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof Node) {
            return this.name.equalsIgnoreCase(((Node) o).name);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(name);
    }

    public abstract int getSize();
}

2. Leaf

File을 Leaf로 구성합니다.

Node를 상속 받아서 구현하였습니다. 이때 파일의 사이즈를 멤버 변수로 잡고 생성자에서 받도록 하였습니다.

public class File extends Node{
    private int size;

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

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

3. Composite

Directory 를 Composite로 구성합니다.

Directory의 사이즈는 해당 Directory에 속한 file을 사이즈들에 의해서 결정 되게 하기 위해서 getSize시 하위 Node를 순회하면서 사이즈의 합을 리턴해 줍니다. 이를 통해서 Directory안에 Directroy가 있는 경우 재귀적으로 사이즈를 계산하게 됩니다.

ls 메서드는 해당 디렉토리에 무엇이 있는지 알기 위해서 만들어본 메서드 입니다.

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

public class Directory extends Node {
    private List<Node> nodes = new ArrayList<>();

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

    public void addNode(Node node) {
        nodes.add(node);
    }

    public void removeNode(Node node) {
        nodes.remove(node);
    }

    @Override
    public int getSize() {
        int size = 0;
        for (Node node : nodes) {
            size+= node.getSize();
        }
        return size;
    }

    public void ls() {
        for (Node node : nodes) {
            System.out.println(" " + node.getName() + " : " + node.getSize());
        }
    }
}

4. 실행 & 결과

public class CompositePatternDemo {
    public static void main(String[] args) {
        File file1 = new File("1번 파일", 10);
        File file2 = new File("2번 파일", 20);
        File file3 = new File("3번 파일", 30);

        Directory subDirectory = new Directory("디렉토리 2");
        subDirectory.addNode(file1);
        subDirectory.addNode(file2);

        Directory directory = new Directory("디렉토리 1");
        directory.addNode(file3);
        directory.addNode(subDirectory);

        System.out.println(directory.getName());
        directory.ls();
        System.out.println("total: " + directory.getSize());

        System.out.println();

        System.out.println(subDirectory.getName());
        subDirectory.ls();
        System.out.println("total: " + subDirectory.getSize());

    }
}

 

이해가 잘 안되시는 분들은 아래 주소에서 다양한 Leaf노드를 설정하고 설명하는 예시를 보시는 것을 추천 드립니다.

gmlwjd9405.github.io/2018/08/10/composite-pattern.html

'Design Pattern > 구조 패턴' 카테고리의 다른 글

Proxy pattern  (0) 2021.05.04
Facade Pattern  (0) 2021.05.04
Decorator Pattern  (0) 2021.05.04
Bridge Pattern  (0) 2021.05.04
Adapter pattern  (0) 2021.05.03