Designing Menus with Composite
Waitress
Waitress는 MenuComponent 인터페이스/추상 클래스 를 통해 Menu 와 Menuitems에 access 한다.
MenuComponent
Menu 와 MenuItem 의 interface를 나타낸다.
abstract class 를 통해 클래스 내에 원하는 기본 메소드 구현 제공
공통연산과 Menu 조작 연산으로 구성
공통연산 : getName, getDescription, getPrice, print
조작연산 : add, remove, getChild
MenuItem
Both Menu and Menus override print()
Menu
we’ll use the getName() andngetDescription() methods to return the name and description of the menu.
Implementing the MenuComponent
package Composite;
public abstract class MenuComponent
{
// 공통 연산
public String getName(){ throw new UnsupportedOperationException(); }
public void print(){ throw new UnsupportedOperationException(); }
public String getDescription() { throw new UnsupportedOperationException(); }
// For Composite
// 추상 클래스에서 추상 메소드와 , 메소드내에서 예외처리 하는 경우를 비교해봄.
public abstract void add(MenuComponent menuComponent); // -->> 비추
public MenuComponent getChild(int idx){ throw new UnsupportedOperationException(); } // -->> 추천, 해당기능이 필요없는 클래스에서 생성하지 않아도됨.
public void remove(MenuComponent menuComponent) { throw new UnsupportedOperationException(); }
// For Leaf
public double getPrice(){ throw new UnsupportedOperationException(); }
}
MenuComponent provides default implementations for every method.
본래 add 메소드도 예외처리 구현했었지만 실험적으로 abstract 메소드로 정의하였다.
public void add(MenuComponent menuComponent) { throw new UnsupportedOperationException(); }
-->> public abstract void add(MenuComponent menuComponent);
the default implementation is UnsupportedOperationException.
MenuItem 이나 Menu 에서 메소드를 원하지 않는다면 사용하지 않아도 된다.
they can just inherit the default implementation.
Implementing the Menu Item
package Composite;
public class MenuItem extends MenuComponent
{
String name, description; double price;
public MenuItem(String name, String description, double price) {
this.name = name;
this.description = description;
this.price = price;
}
// 공통 연산
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
// 추상클래스에 추상메소드 정의시,
// 특정메소드가 필요가 없는 경우에도 Override로 생성되어
// 이중으로 메소드를 정의해야되는 번거로움이 있다.
@Override
public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
} // ->> 해당 메소드를 추상클래스에서 일반 메소드로 변환시켜 정의하는 것이 좋다.
@Override
public void print() {
System.out.print("" + getName());
System.out.println(", " + getPrice());
System.out.println(" -- "+ getDescription());
}
// Leaf
@Override
public double getPrice() {
return price;
}
}
MenuComponent를 상속하여 메소드를 재정의할 수 있다.
그렇지만 add 와 같은 원하지 않는 메소드를 재정의 해야하는 번거러움이 있다.
그것을 abstract class 에서 the default implementation ( throw new UnsupportedOperationException(); )
Implementing the Composite Menu
package Composite;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Menu extends MenuComponent
{
List<MenuComponent> menuComponents = new ArrayList<>();
String name, description;
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
// 공통 연산
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public void print() {
System.out.println(getName()+ " : "+getDescription());
Iterator iterator = menuComponents.iterator();
while(iterator.hasNext())
{
MenuComponent menuComponent = (MenuComponent) iterator.next();
menuComponent.print(); // 각 child 에게 print 위임
}
System.out.println();
}
// For Composite
@Override
public void add(MenuComponent menuComponent) {
menuComponents.add(menuComponent);
}
@Override
public void remove(MenuComponent menuComponent) {
super.remove(menuComponent);
}
@Override
public MenuComponent getChild(int idx) {
return super.getChild(idx);
}
}
update the Waitress code
package Composite;
// Client
// Component 인터페이스만을 사용
public class Waitress
{
MenuComponent allMenus;
public Waitress(MenuComponent allMenus) {
this.allMenus = allMenus;
}
public void printMenu(){
allMenus.print();
}
}
runtime
Now for the test drive
package Composite;
public class main {
public static void main(String[] args) {
// Let's first create all the menu objects
MenuComponent pancakeHouseMenu = new Menu("Pancake House Menu", "Breakfast");
MenuComponent dinerMenu = new Menu("Diner Menu", "Diner");
MenuComponent cafeMenu = new Menu("Cafe Menu", "coffee");
MenuComponent dessertMenu = new Menu("DESSERT MENU", "Dessert of course");
MenuComponent allMenus = new Menu("All Menus", "All Menus combined");
// Menu Component
allMenus.add(pancakeHouseMenu);
allMenus.add(dinerMenu);
allMenus.add(cafeMenu);
// add menu items here
dinerMenu.add(new MenuItem(
"Pasta",
"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
8900 ));
dinerMenu.add(dessertMenu);
dessertMenu.add(new MenuItem(
"Apple Pie",
"Apple pie with a flakey crust, topped with vanilla icecream",
15900));
// add more menu items here
Waitress waitress = new Waitress(allMenus);
waitress.printMenu();
}
}
책 참고 : Head First Design Patterns
댓글