컴포지트 패턴

반응형
반응형

 

오늘은 다른 방식으로 이 패턴을 이해하려고합니다. 이 패턴은 생각보다 구현이 단순하기 때문에

이해하는데 오히려 걸림돌이 되는 그런 패턴인것 같습니다. 그럼에도 그냥 한번 해보겠습니다. 

 

오늘은 제가 직접 예제를 만들지 않고 유튜버 이야기'sG님의 코드를 분석하는 시간을 가져볼까합니다. 컴포짓트? 이건 과연 뭘까요? 컴포짓트는 한글로 혼합물이라는 뜻이라고 합니다. 혼합물의 가장 큰 특징은 2개 이상의 액체를 섞었다는 것이 그 특징입니다. 액체를 섞게되면 뭐가 섞였는지 잘 모릅니다. 하지만 저희는 액체를 섞고 싶은게 아닙니다. 저희가 섞고 싶은 건 객체입니다. 하지만 객체는 액체와 달리 섞는 방법이 정해져 있지 않습니다.  그래서 디자인 패턴에서 사용한 방법이 바로 트리로 만드는 것입니다. 물론, 자료구조의 트리와는 다를 수 있다는 점 양해 부탁드립니다. 여기서의 트리는 서로 다른 두개가 나눠졌다라고 생각하면 될것 같습니다. 

 

이게 기본입니다. 커다란 물체 하나를 거기서 2개로 쪼갭니다. 하지만, 그 두개는 상위 클래스를 특징이 고스란히 담겨져 있습니다.  그러니까 하나에서 2개 이상이 나올수 있으니... 그 하나에서 나머지를 관리하는 리스트 같은 걸로 만들면 편할겁니다. 왜냐하면 이 방법이 가장 적절한 방법이기 때문입니다. 물론, 여기서 배열을 쓰다던지, 아니면 진짜로 자료구조'트리'를 만들어서 사용하던지.. 그거야 자유입니다. 하지만 하나 확실한 점은 여러개의 부모는 하나라는 이야기가 됩니다. 이제 본격적으로 코드를 뜯어봅시다. 

 

이야기'sG님은 파일 시스템을 예로 두셨습니다.

일단 파일을 만듭니다.

public class File{

    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

 원래는 클래스 옆에 뭔가가 붙어야 하는데 일단은 무시해둡니다. 

코드를 보면 데이터를 받아서 저장하는 로직을 가지고 있습니다. set으로 data를 저장하게 되면 File클래스는 객체가 될때, 이 data를 가지게 됩니다. 아마 Object로 하신 이유는 아무래도 모든 객체명을 다 받겠다는 의지라 생각이 되는군요. 물론, 지금은 제네릭을 사용하겠지만요. 바로 이렇게요.

public class File<T> {

    private T data;


    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

이렇게 되면 File를 만들게 됩니다. 그런데 파일은 보통 어디에 있죠? 바로 폴더에 있습니다. 그래서 폴더도 만들어 봅시다. 

public class Folder<T> {

    List<T> children = new ArrayList<>();


    public List<T> getChildren() {
        return children;
    }

    public boolean addComponent(T component) {
        return children.add(T);
    }

    public boolean removeComponent(T component) {
        return children.remove(component);
    }
}

폴더도 만들었습니다. 근데 문제가 발생했습니다. 폴더를 통해 파일은 저장시킬 수 있는데,

폴더도 따지고 보면 파일입니다. 만약, 위 코드가 가능하다고 한다면 그냥 Foler클래스에 File만 추가되는 리스트형태로 구현 될 수 밖에 없을 겁니다. 코드를 잘 보시면 componet라는게 보입니다. 다 알다시피 요소라는 뜻을 가지고 있습니다. 즉, 요소로 만들어서 넣겠다는 의미죠. 본격적으로 요소 클래스를 만들어 봅시다.

public class Component {
    private String name;

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

    public String getName() {
        return name;
    }
}

 

요소 클래스를 만들었습니다. 요소가 될만한 것을 생각해봅시다. 바로 파일과 폴더입니다. 이 두개는 이 구조에서 요소입니다. 이를 leaf라고 부른다고 하는데, 사실 잘 모르겠습니다. 나중에 자료구조 트리를 배우게 되면 그때 다시 언급했으면 좋겠네요. 자 이제 요소를 파일과 폴더 클래스에 추가줍시다.

public class File<T> extends  Component {

    private T data;

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

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

이제 부터  파일은 Componet(요소)입니다. 참고로 Component클래스는 인터페이스로 만들어도 된다고 합니다.

폴더도 똫같이 해줍니다. 폴더 같은 경우는 코드가 많이 바뀔 것 같습니다.

public class Folder extends Component{

    List<Component> children = new ArrayList<>();

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


    public List<Component> getChildren() {
        return children;
    }

    public boolean addComponent(Component component) {
        return children.add(component);
    }

    public boolean removeComponent(Component component) {
        return children.remove(component);
    }
}

 아까는 제네릭을 사용해서 모든 객체에 접근?할 수 있게 했지만, 이번에는 요소 객체만 추가하겠다고 명시해줍니다.

이렇게 되면 폴더도 요소가 되기 때문에 폴더가 폴더를 또 그 폴더가 폴더를 폴더가 폴더를 폴더가 또 그 폴더를 하는 상황도 만들 수 있을 것 같습니다.

 

여기까지 읽어도 그래서 어떻게 사용하냐는 생각이 들지도 모릅니다. 정확하게는 모르지만 공통 부분을 만들어서 그 부분을 배열이나 리스트등과 같은 자료구조에 저장하는 구조라 생각이 듭니다.

 

즉, 핵심은 컴포넌트입니다. 이게 없다면 폴더와 파일은 서로다른 객체라 생각이 들기때문에 관리하기가 굉장히 어려울겁니다. 그렇기 때문에 컴포넌트 패턴을 이용하면 파일관리?에 용이 할거라 예상합니다.

 

아직도 이해가 되지 않았다면 죄송합니다. 이게 제 한계입니다.

 

반응형

'디자인패턴' 카테고리의 다른 글

팩토리 패턴  (0) 2020.05.06
데코레이터 패턴  (0) 2020.05.02
옵저버 패턴  (0) 2020.04.28
퍼사드 패턴  (0) 2020.04.23
브릿지 패턴  (0) 2020.04.22

댓글

Designed by JB FACTORY