Composite 패턴은 Structural pattern이다.
그룹 객체와 단일 객체 사이의 접근 방식을 통일하는 패턴이다!
문제상황
택배 상자 속 무게를 통해 택배 비용을 계산하는 프로그램이 있다. 택배 안에는 바지, 양말, 금 등등 다양한 물건이 들어가는데 상자 안에 상자가 들어가는 것도 가능하다.
private List<Trousers> trousers = new ArrayList<>();
private List<Socks> socks = new ArrayList<>();
private List<Gold> golds = new ArrayList<>();
private List<Box> boxes = new ArrayList<>();
일단 택배 안에 있는 물건을 ArrayList로 관리하는 가장 단순한 방법을 택해보자. 새로운 양말이 추가되면 socks에 add하고 박스가 추가되면 boxes에 add하고...
for (Trousers t : trousers) {
tPrice += t.price();
}
무게를 재고 가격을 더하는 과정까지 물건 별로 관리하는 문제가 생긴다. ➡ 물건 상황에 변경이 있을 때마다 기존 코드를 변경해야 한다. OCP 위반
Object를 이용한 해결책
Object는 모든 클래스의 부모 클래스다.
private List<Object> items = new ArrayList<>();
그렇다면 Object로 리스트를 받아 사용하면 되지 않을까?
for (Object o : items) {
if (o instanceof Trousers) tPrice += ((Trousers)o).price();
else if (o instanceof Socks) tPrice += ((Socks)o).price();
else if (o instanceof Gold) tPrice += ((Gold)o).price();
else tPrice += ((Box)o).price();
}
return tPrice;
물품 별로 반복문을 관리할 필요 없이 단체로 반복문을 관리할 수 있다.
public void addItems (Objects o) { items.add(o); }
새로운 아이템을 추가할 때에도 물품 별로 add 메서드를 관리할 필요 없고 하나의 add 메서드 만을 통해 리스트를 관리할 수 있다. 그럼 완벽하냐? 아니다!!!! 여전히 OCP를 위반한다. 새로운 타입의 물건이 들어오면 반복문에 새로운 if문을 추가해야 하기 때문이다. 예를 들어 셔츠가 추가됐다면
for (Object o : items) {
if (o instanceof Trousers) tPrice += ((Trousers)o).price();
else if (o instanceof Socks) tPrice += ((Socks)o).price();
else if (o instanceof Gold) tPrice += ((Gold)o).price();
else if (o instanceof Shirts) tPrice += ((Shirts)o).price();
else tPrice += ((Box)o).price();
}
return tPrice;
이렇게 반복문에 새로운 조건문이 계속 추가된다.
택배로 보낼 수 있는 항목을 포함하는 개념(ParcelItem) 생성
박스, 골드, 삭스 등등 택배로 보낼 수 있는 걸 포함하는 개념을 생성한다. Object는 너무 많은 것을 포함하는 개념이다.
public abstract class ParcelItem {
protected int weight;
public ParcelItem(int weight) {this.weight = weight;}
public abstract int price();
}
public class Trousers extends ParcelItem{
public Trousers(int weight) {
super(weight);
}
public int price() {
return this.weight/100*200;
}
}
이렇게 포함하는 개념을 상속 받아 물품 별로 가격만 조정하면 된다.
public class Box extends ParcelItem{
private List<ParcelItem> items = new ArrayList<>();
public Box(int weight) {
super(weight);
}
public int price() {
int totalPrice = 0;
for (ParcelItem item : items) {
totalPrice += item.price();
}
return totalPrice;
}
public void addItems (ParcelItem item) { items.add(item); }
}
박스도 박스에 담길 수 있는 존재이기 때문에 ParcelItem을 상속 받는다.
Composite 패턴은 트리 구조와 유사하다!!
Composite 패턴은 Decorator 패턴과 유사한 모습을 가진다. Composite 패턴은 여러 상위 개념과 연관관계를 맺지만 Decorator는 단일 개념과 연관된다는 차이가 있다.
https://refactoring.guru/ko/design-patterns/composite
복합체 패턴
/ 디자인 패턴들 / 구조 패턴 복합체 패턴 다음 이름으로도 불립니다: 객체 트리, Composite 의도 복합체 패턴은 객체들을 트리 구조들로 구성한 후, 이러한 구조들과 개별 객체들처럼 작업할 수 있
refactoring.guru
'공부 > 소프트웨어공학' 카테고리의 다른 글
[디자인패턴] 추상 팩토리(Abstract Factory) 패턴이란? (0) | 2024.11.26 |
---|---|
[디자인패턴] 팩토리 메서드(Factory Method) 패턴이란? (+ GoF Factory Method Pattern) (0) | 2024.11.17 |
[디자인패턴] 템플릿 메서드(Template Method) 패턴이란? (0) | 2024.11.15 |
[디자인패턴] 데코레이터(Decorator) 패턴이란? (0) | 2024.11.14 |
[디자인패턴] 빌더(Builder) 패턴이란? (1) | 2024.11.12 |