TOPIC:我们的任务是想实现一个树形结构的菜单,如下~
/**
* @Description: 组件的抽象类,菜单组件的角色是为叶节点和组合节点提供一个公共的接口。
* @author: cuixiuyin
* @date: 2018/12/29 08:59
*/
public abstract class MenuComponent {
/**
* @Description 组合节点(菜单)的方法组织在一起
* @author cuixiuyin
* @date 2018/12/29 09:03
*/
public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public MenuComponent getChild(int i) {
throw new UnsupportedOperationException();
}
/**
* @Description 叶子节点(菜单项)的方法组织在一起、其中有一些也可以用于组合节点(菜单)上
* @author cuixiuyin
* @date 2018/12/29 09:03
*/
public String getName() {
throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException();
}
public Double getPrice() {
throw new UnsupportedOperationException();
}
public Boolean isVegetarian() {
throw new UnsupportedOperationException();
}
/**
* @Description 相关操作
* @author cuixiuyin
* @date 2019/01/02 09:04
*/
public void print() {
throw new UnsupportedOperationException();
}
}
组合部件为叶子节点和组合节点定义了统一的接口。所有的操作,如果子类没有实现,我们默认抛出一个 UnsupportedOperationException 异常。
为了要保持透明性,组合内所有的对象都必须实现这个接口,否则客户就必须操心哪个对象是用哪个接口,这就失去了组合模式的意义。
/**
* @Description: 菜单项 (叶子节点)
* @author: cuixiuyin
* @date: 2018/12/29 09:09
*/
public class MenuItem extends MenuComponent {
/**
* 名称
*/
private String name;
/**
* 描述
*/
private String description;
/**
* 是否为素食
*/
private Boolean vegetarian;
/**
* 价格
*/
private Double price;
public MenuItem(String name, String description, Boolean vegetarian, Double price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public Boolean isVegetarian() {
return vegetarian;
}
@Override
public Double getPrice() {
return price;
}
@Override
public void print() {
System.out.print(getName() + "--" + getDescription() + "," + getPrice() + ",");
if (isVegetarian()) {
System.out.print("(v)");
}
System.out.println();
}
}
叶子节点没有子节点,只有一些菜单项上的类目,不存在下一级结构的维护。
/**
* @Description: 菜单(组合节点)
* @author: cuixiuyin
* @date: 2018/12/29 09:19
*/
public class Menu extends MenuComponent {
/**
* 可能持有菜单项或其他菜单
*/
List<MenuComponent> list = new ArrayList<>();
/**
* 名称
*/
private String name;
/**
* 描述
*/
private String description;
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
@Override
public void add(MenuComponent menuComponent) {
list.add(menuComponent);
}
@Override
public void remove(MenuComponent menuComponent) {
list.remove(menuComponent);
}
@Override
public MenuComponent getChild(int i) {
return list.get(i);
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
/**
* @Description 递归 —— 不仅打印出菜单本身的信息,也打印出菜单内所有组件的内容:其他菜单和菜单项目。
* @author cuixiuyin
* @date 2018/12/29 09:26
*/
@Override
public void print() {
System.out.println("\n" + getName() + "," + getDescription());
System.out.println("--------------------");
Iterator<MenuComponent> iterator = list.iterator();
while (iterator.hasNext()) {
MenuComponent component = iterator.next();
component.print();
}
}
}
组合节点维护了一个集合,这个集合可以持有其他菜单项(叶子节点)或者菜单(组合节点)。
public class Waitress {
private MenuComponent menuComponent;
public Waitress(MenuComponent menuComponent) {
this.menuComponent = menuComponent;
}
public void printMenu() {
menuComponent.print();
}
}
public class Test {
public static void main(String[] args) {
// 1、创建所有的菜单对象
MenuComponent breakfast = new Menu("早餐菜单", "Breakfast");
MenuComponent lunch = new Menu("午餐菜单", "Lunch");
MenuComponent dinner = new Menu("晚餐菜单", "Dinner");
MenuComponent dessert = new Menu("晚餐甜点", "Dessert");
// 2、创建顶层菜单
MenuComponent top = new Menu("顶层菜单", "Top");
top.add(breakfast);
top.add(lunch);
top.add(dinner);
// 3、晚餐菜单中加入甜点
dinner.add(dessert);
// 4、构建每份菜单中的菜单项(叶子节点)
breakfast.add(new MenuItem("dumplings", "饺子", false, 10.0));
breakfast.add(new MenuItem("bread", "面包", true, 7.0));
breakfast.add(new MenuItem("mile", "牛奶", false, 5.0));
lunch.add(new MenuItem("rice", "米饭", true, 2.0));
lunch.add(new MenuItem("burger", "汉堡", false, 6.0));
lunch.add(new MenuItem("vegetables", "蔬菜", true, 1.0));
dinner.add(new MenuItem("noodle", "面条", true, 4.0));
dessert.add(new MenuItem("cake", "蛋糕", true, 3.0));
// 5、把最顶层的组合给服务员,以便可以获取到所有订单
Waitress waitress = new Waitress(top);
waitress.printMenu();
}
}