Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

컴포지트 패턴 #141

Open
Baemung opened this issue Nov 7, 2021 · 0 comments
Open

컴포지트 패턴 #141

Baemung opened this issue Nov 7, 2021 · 0 comments

Comments

@Baemung
Copy link
Collaborator

Baemung commented Nov 7, 2021

Composite

image

Composite Pattern 이란?

Composite Pattern은 객체들을 트리 구조로 구성한 다음, 이러한 구조를 개별 객체인 것처럼 사용할 수 있는 구조 설계 디자인 패턴이다.

Problem

Composite Pattern을 사용하는 것은 어플리케이션의 핵심 모델을 트리로 나타낼 수 있는 경우에만 의미가 있다.

image

예를 들어, ProductBox라는 두 가지 유형의 객체가 있다고 가정해 보자.

Box에는 여러 Product와 여러 개의 작은 Box가 포함될 수 있다. 이러한 작은 상자에는 일부 Product 또는 더 작은 Box 등이 포함될 수 있다.

그 다음 이러한 클래스를 사용하는 주문 시스템을 만들기로 결정했다고 추가적으로 가정해 보자.

주문에는 박스 포장이 없는 Prodcut와, 작은 Box와 Product들로 채워진 Box가 포함될 수 있다.

이 때, 주문의 총 가격을 어떻게 결정해야할까?

당장 떠오르는 러프한 결정 방법으로는 포장된 상자를 모두 풀고 모든 제품을 살펴본 다음 합계를 계산하는 방법이 있다. 이 방법은 현실세계에서 이런식으로 할 수 있다.

하지만, 프로그램에서는 이건 그렇게 간단한 문제가 아니다.

그렇다면 어떤 해결 방법이 있을까?

Solution

Composite pattern을 적용한다면, 토탈 가격을 계산할 수 있는 공통 인터페이스를 선언하고 ProductBox가 이를 구현하는 방식으로 문제를 해결할 수 있다.

이러한 구조는 어떻게 작동할까?

Product의 경우, 단순히 Product의 가격을 리턴한다.

Box의 경우 Box에 들어 있는 각 아이템들을 살펴보고 각각 아이템에 대한 가격을 모두 구한 다음 결과적으로 이 상자에 대한 토탈 가격을 리턴한다.

image

만약 Box의 아이템이 더 작은 Box라면, 재귀적으로 접근하여 작은 Box 또한 자신이 담겨있는 큰 Box와 동일한 매커니즘으로 가격을 구할 수 있다.


이러한 접근 방식의 가장 큰 장점은 트리를 구성하는 객체들의 구체적인 클래스에 대해 신경을 쓰지않아도 된다는 점이다.

Box속 객체가 Product인지 또 다른 Box인지 알 필요없이 공통 인터페이스를 통해 모두 동일하게 처리할 수 있다.

Structure

image

Composite Pattern의 구조는 위에서 설명했듯 트리구조이고, 크게 4가지로 구조를 구분할 수 있다.

  1. Component : Component 인터페이스는 트리의 단일 객체(like Product)와 복합 객체(like Box) 모두에게 공통 인터페이스를 제공한다.
  2. Leaf : Leaf는 일반적인 트리구조에서 Leaf Node와 같은 의미이다. Composite Pattern에서 Leaf는 트리의 단순 요소(like Product)만으로 이루어져 있으므로 대부분의 실제 작업을 수행한다.
  3. Container : Container는 Composite와 동일한 의미이며, Container는 하위 요소들을 가진 요소(like 작은 Box를 가진 Box)이다.

    자식들의 구체적인 클래스를 알지못하며 공통 인터페이스를 통해 모든 하위 요소와 함께 작동한다.

    요청을 받으면 본인이 처리할 수 있는 부분은 직접 처리하고, 하위 요소중 자신과 같은 Container가 있다면 자식 Container에게 작업을 위임하여 결과를 리턴받고 결과를 종합하여 응답한다.
  4. Client : Client는 Component 인터페이스를 통해 모든 구성요소와 함께 작동한다. 결과적으로 Client는 트리의 단순 요소 또는 복잡한 요소 모두에 대해 동일한 방식으로 작업할 수 있게된다.

Implementation

지금까지의 Product Box를 예시로 Composite Pattern을 간단하게 구현해보자.

Product.interface

public interface Products {
	int getPrice();
}

Product.class

public class Product implements Products{
	int price = 1000;
	
	@Override
	public int getPrice() {
		return this.price;
	}
}

Box.class

import java.util.*;

public class Box implements Products{
	List<Products> products = new ArrayList<Products>();
	int price;
	
	public void addProduct(Products product) {
		products.add(product);
	}
	
	@Override
	public int getPrice() {
		for(Products product : products) this.price += product.getPrice();
		return this.price;
	}
}

Main.class

public class Main {
	public static void main(String[] args) {
		Box box1 = new Box();
		box1.addProduct(new Product());
		box1.addProduct(new Product());
		box1.addProduct(new Product());
		
		Box box2 = new Box();
		box2.addProduct(new Product());
		box2.addProduct(new Product());
		box2.addProduct(box1);
		
		Box product = new Box();
		product.addProduct(new Product());
		product.addProduct(box2);
		
		System.out.println(product.getPrice());
	}
}

출력 : 6000

Composite Pattern의 장단점

장점

  • 객체들이 모두 같은 타입으로 취급되기 때문에 새로운 클래스 추가가 용이하다.
  • 단일 객체, 복합 객체 구분하지 않고 코드 작성이 가능하다.

단점

  • 설계를 일반화 시켜 객체간의 구분, 제약이 힘들다.

정리하자면, 컴포지트 패턴의 장점은 사용자 입장에서는 이게 단일 객체인지 복합 객체인지 신경쓰지 않고 사용할 수 있다는 장점이 있지만 설계가 지나치게 범용성을 갖기 때문에 새로운 요소를 추가할 때 복합 객체에서 구성 요소에 제약을 갖기가 힘들다.


Reference : https://refactoring.guru/design-patterns/composite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant