[디자인패턴] 컴퍼지트패턴(Composite Pattern)

고지훈·2021년 9월 29일
2

DesignPattern

목록 보기
8/16
post-thumbnail

컴퍼지트패턴(Composite Pattern)

컴퍼지트패턴은 구조 패턴 중 하나로, 객체들의 관계를 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴이다. 사용자는 컴퍼지트패턴을 통해 단일 객체와 복합 객체 모두 동일하게 다룰 수 있다.

  1. 전체-부분의 관계를 갖는 객체들 사이의 관계를 정의할 때 유용하다.
  2. 클라이언트는 전체와 부분을 구분하지 않고 동일한 인터페이스를 사용할 수 있다.
  3. 구조(Structural)패턴 중 하나 => 아래 설명 참고


사진출처: 위키백과

  • Component
    • 컴포넌트는 클라이언트가 composition내의 오브젝트들을 다루기 위해 제공되는 인터페이스를 말한다.
    • 컴포넌트는 인터페이스 또는 추상 클래스로 정의되며 모든 오브젝트들에게 공통되는 메소드를 정의해야한다.
  • Leaf
    • composition내 오브젝트들의 행동을 정의한다. 이는 복합체를 구성하는데 중요한 요소이며, 베이스 컴포넌트를 구현한다.
    • Leaf는 다른 컴포넌트에 대해 참조를 가지면 안된다.
  • Composite
    • Leaf객체들로 이루어져 있으며 컴포넌트 내 명령들을 구현한다.

[구조패턴]
구조(Structural)패턴은 작은 클래스들을 상속과 합성을 이용해 더 큰 클래스를 생성하는 방법을 제공하는 패턴

구조패턴을 사용하면 독립적으로 개발한 클래스 라이브러리를 하나로 사용할 수 있는 장점이 있다. 또 여러 인터페이스를 합성하여 서로 다른 인터페이스들의 통일된 추상을 제공한다.

구조패턴의 중요한 포인트는 인터페이스나 구현을 복합하는것이 아닌, 객체를 합성하는 방법을 제공한다는 것이다. => 런타임 단계에서 복합 방법이나 대상을 변경할 수 있다는 점에서 유연성을 갖는다.


컴퍼지트패턴 구현

컴퍼지트패턴을 적용하기 위해 실생활 예를 활용해보자!

그림판에 삼각형, 사각형, 동그라미를 만들고 삼각형과 사각형을 그룹화했다고 가정하자! 만들어진 도형들을 모두 빨간색으로 색칠하려고 한다.
이때 우리가 채우기 버튼을 누를 때 선택하는 것이 어떤 도형인지, 혹은 그룹인지에 대해 구분하지 않아도 된다. 그림판에는 도형 하나에 대한 채우기 기능과 그룹에 대한 채우기 기능이 같다.
컴퍼지트 패턴은 전체 도형을 하나의 도형으로 관리할 수 있다는 특징을 갖고 있다.

1. Component
Component에서는 Leaf와 Composite의 공통이 되는 메소드를 정의해야한다.
Shape인터페이스 내 각각 도형에 색을 입히는 draw()메소드를 정의해보자

// Shape.java
public interface Shape {
    public void draw(String paintColor);
}

2. Leaf
Leaf객체들은 복합체에 포함되는 요소로, Component를 구현해야한다.

// Triangle.java
public class Triangle implements Shape {
    public void draw(String paintColor) {
    	System.out.println("삼각형이 다음 색상으로 색칠되었습니다. : " + paintColor);
    }
}
// Square.java
public class Square implements Shape {
    public void draw(String paintColor) {
    	System.out.println("사각형이 다음 색상으로 색칠되었습니다. : " + paintColor);
    }
}
// Circle.java
public class Circle implements Shape {
    public void draw(String paintColor) {
    	System.out.println("동그라미가 다음 색상으로 색칠되었습니다. : " + paintColor);
    }
}

3. Composite
Composite객체는 Leaf객체를 포함하고 있고, Component를 구현할 뿐만 아니라 Leaf그룹에 대해 add와 remove를 할 수 있는 메소드를 클라이언트에게 제공한다.

// Drawing.java
public class Drawing implements Shape {
    private List<Shape> shapes = new ArrayList<>();
    
    @Override
    public void draw(String paintColor) {
    	for(Shape shape : shapes) {
        	shape.draw(paintColor);
        }
    }
    
    public void add(Shape s) {
    	this.shapes.add(s);
    ]
    
    public void remove(Shape s) {
    	this.shapes.remove(s);
    }
    
    public void clear() {
    	System.out.println("모든 도형을 제거합니다.");
        this.shapes.clear();
    }
}

위 코드에서 중요한 것은 Composite의 객체 또한 Component를 구현해야한다는 것이다. 그렇게 해야만 클라이언트가 Composite객체에 대해 다른 Leaf와 동일하게 취급할 수 있기 때문이다.

// CompositePattern.javva
public class CompositePattern {
    public static void main(String args[]) {
        Shape triangle = new Triangle();
        Shape circle = new Circle();
        Shape square = new Square();
        
        Drawing drawing = new Drawing();
        drawing.add(triangle);
        drawing.add(circle);
        drawing.add(square);
        
        drawing.draw("빨간색");
        
        List<Shape> shapes = new ArrayList<>();
        shapes.add(drawing);
        shapes.add(new Triangle());
        shapes.add(new Circle());
        
        for(Shape shape : shapes) {
        	shape.draw("초록색");
        }
    }
}

위의 코드에서 보았듯이, drawing객체를 통해 Triangle, Circle, Sqaure등 Leaf객체를 그룹으로 묶어서 한번에 동작할 수 있다. 그룹 뿐만 아니라 다른 도형들도 마찬가지로 Shape인터페이스를 구현하고 있기 때문에, 함께 취급되는 것을 확인할 수 있다.

컴퍼지트패턴 학습 시 참고 블로그: https://readystory.tistory.com/131

profile
"계획에 따르기보다 변화에 대응하기를"

0개의 댓글