[Design Pattern] 컴포지트 패턴(Composite Pattern)

in·2023년 10월 18일
0

Design Pattern

목록 보기
8/8

📌 컴포지트 패턴(Composite Pattern)

구조 패턴 중 하나로 객체들의 관계를 트리 구조로 구성하여 부분-전체 계층을 표현하는 패턴
➡️ 단일 객체와 복합 객체 모두 동일하게 다룰 수 있음

  • 전체-부분의 관계를 갖는 객체들 사이의 관계를 정의할 때 유용
  • 클라이언트는 전체와 부분을 구분하지 않고 동일한 인터페이스 사용 가능
  • 구조 패턴 중 하나

Component

  • 클라이언트가 composition 내의 오브젝트들을 다루기 위해 제공되는 인터페이스
  • 인터페이스 또는 추상 클래스로 정의되며 모든 오브젝트들에게 공통되는 메소드를 정의해야함

Leaf

  • composition 내 오브젝트들의 행동 정의
    ➡️ 복합체를 구성하는데 중요한 요소이며 베이스 컴포넌트 구현
  • 다른 컴포넌트에 대해 참조를 가지면 안됨

Composition

  • Leaf 객체들로 이루어져 있으며 컴포넌트 내 명령들을 구현

예제

Ex1. 그림판에 삼각형, 사각형, 동그라미를 만들고 삼각형과 사각형을 그룹화 했다고 가정

만들어진 도형을 모두 빨간색으로 색칠하려면?
➡️ 채우기 버튼을 누를 때 선택하는 것이 어떤 도형인지 혹은 그룹인지에 대해 구분하지 않아도 된다. 그림판에는 도형 하나에 대한 채우기 기능과 그룹에 대한 채우기 기능이 같다.

Component
Component에서는 Leaf와 Composite의 공통이 되는 메소드 정의
Shpape 인터페이스 내 각 도형에 색을 입히는 draw() 메소드 정의

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

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);
    }
}

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();
    }
}

Client

// 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("초록색");
        }
    }
}

Ex2.

Component 클래스

public class Component {
    public void operation() {
        throw new UnsupportedOperationException();
    }
    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    public Component getChild(int i) {
        throw new UnsupportedOperationException();
    }
}

➡️ Leaf 클래스와 Composite 클래스가 상속하는 Component 클래스로 Leaf 클래스에서 사용하지 않는 메소드 호출 시 exception을 발생시키게 구현

Leaf 클래스

public class Leaf extends Component {
    String name;
    public Leaf(String name) {
        ...
    }

    public void operation() {
        .. something ...
    }
}

Composite 클래스

public class Composite extends Component {
    ArrayList components = new ArrayList();
    String name;

    public Composite(String name) {
        ....
    }

    public void operation() {
        Iterator iter = components.iterator();
        while (iter.hasNext()) {
            Component component = (Component)iter.next();
            component.operation();
        }
    }
    public void add(Component component) {
        components.add(component);
    }

    public void remove(Component component) {
        components.remove(component);
    }

    public Component getChild(int i) {
        return (Component)components.get(i);
    }
}

장단점

장점 : Leaf 클래스가 children 관리 함수 호출 시 complie time에 문제를 확인할 수 있다.
단점 : Leaf 클래스와 Composite 클래스를 구분하여야 한다.

[참고 자료]

🔗링크
🔗링크

0개의 댓글