Composite Pattern의 특징
트리와 같은 계층적인 정보에서
하위에 정보가 없는 리프노드, 자식이 있는 논 리프노드 가 있을 때,
이런 서로 다른 노드를 같은 인터페이스를 통하여 일관된 방식으로 프로그래밍할 수 있게 함
public class MenuItem extends MenuComponent { String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name, String description, boolean vegetarian,
double price) {
...
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public double getPrice() {
return price;
}
public boolean isVegetarian() {
return vegetarian;
}
public void print() {
System.out.print(" " + getName());
if (this.isVegetarian()) System.out.println("(v)");
System.out.println(", " + getPrice());
System.out.println(" --" + getDescription());
}
}
public class Menu extends MenuComponent {
ArraryList menuComponents = new ArrayList();
String name;
String description;
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
public void add(MenuComponent menuComponent) {
menuComponents.add(menuComponent); }
public void remove(MenuComponent menuComponent) {
menuComponents.remove(menuComponent);
}
public MenuComponent getChild(int i) {
return (MenuComponent)menuComponents.get(i);
}
public String getName() {
return name;
}
public String getDescription () {
return description;
}
public void print() {
Iterator iterator = menuComponents.iterator();
while (iterator.hasNext()) {
MenuComponent menuComponent = (MenuComponent)iterator.next();
menuComponent.print();
}
}
}
주목할 포인트
- print에서 Iterator 사용
- MenuComponent menuComponent = (MenuComponent)iterator.next(); 에서 MenuComponent가 Menu 일수도 있고 MenuItem일수도 있음, But 특정 클래스로 좁히면 좁힐수록 확장하기 어렵고 수정에 대처하기 어려운 문제(OCP 위반) 발생하기에 상위의 MenuComponent를 사용
전체 트리에서의 Iterator 만드는 법
트리 순회로 배운 preorder, inorder, postorder 방식을 Iterator에 접목시킴
=> 비슷한 방식으로 3차원 자료구조 혹은 n 차원 자료구조여도 선형으로 만들어줄 수 있는 알고리즘이 있다면 접목시켜 Iterator 시켜줄 수 있음
public class CompositeIterator implements Iterator {
Stack stack = new Stack();
public CompositeIterator(Iterator iterator) {
stack.push(iterator);
}
public Object next() {
if (hasNext()) {
Iterator iterator = (Iterator)stack.peek();
MenuComponent component = (MenuComponent)iterator.next();
// 루트노드의 자식노드들의 Iterator를 스택에 넣어준다
if (component instance of Menu)
stack.push(component.createIterator());
return component;
}
else
return null;
}
public boolean hasNext() {
if (stack.empty())
return false;
Iterator iterator = (Iterator)stack.peek();
if (!iterator.hasNext()) {
stack.pop();
return hasNext();
}
else
return true;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
public void printAllMenu() {
Iterator iterator = allMenus.createIterator();
while (iterator.hasNext()) {
MenuComponent menuComponent =(MenuComponent)iterator.next();
menuComponent.print();
}
}
Decorator 패턴과 매우 유사
recursive composition을 갖고 있는 등...
But, 의도가 다르다
Decorator 패턴은 서브 클래스를 추가하지 않고 책임을 추가할 수 있게 하는 패턴이였고
Commposite은 트리를 만들 수 있게 해주는 것
반응형
'독서 기록 > 디자인패턴' 카테고리의 다른 글
[디자인패턴] 헤드퍼스트 디자인패턴 Chap.10 (Feat. 상태 패턴) (0) | 2022.11.01 |
---|---|
[디자인패턴] 헤드퍼스트 디자인패턴 Chap.3 (Feat. 데코레이터 패턴) (0) | 2022.11.01 |
[디자인패턴] Iterator 패턴 (0) | 2022.10.24 |
[디자인 패턴] SOLID 원칙 (0) | 2022.10.18 |
[디자인 패턴] 중재자 패턴 vs 옵저버 패턴 (0) | 2022.10.17 |
댓글