1、概述
2、结构
组合模式主要包含三种角色:
- 抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。
- 树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。
- 叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位。
3、软件菜单例子
如下图,我们在访问别的一些管理系统时,经常可以看到类似的菜单。一个菜单可以包含菜单项(菜单项是指不再包含其他内容的菜单条目),也可以包含带有其他菜单项的菜单,因此使用组合模式描述菜单就很恰当,我们的需求是针对一个菜单,打印出其包含的所有菜单以及菜单项的名称。
要实现该案例,我们先画出类图:
//菜单组件 不管是菜单还是菜单项,都应该继承该类
public abstract class MenuComponent {
protected String name;
protected int level;
//添加菜单
public void add(MenuComponent menuComponent){
throw new UnsupportedOperationException();
}
//移除菜单
public void remove(MenuComponent menuComponent){
throw new UnsupportedOperationException();
}
//获取指定的子菜单
public MenuComponent getChild(int i){
throw new UnsupportedOperationException();
}
//获取菜单名称
public String getName() {
return name;
}
public void print(){
throw new UnsupportedOperationException();
}
}
这里的MenuComponent定义为抽象类,因为有一些共有的属性和行为要在该类中实现,Menu和MenuItem类就可以只覆盖自己感兴趣的方法,而不用搭理不需要或者不感兴趣的方法,举例来说,
Menu类可以包含子菜单,因此需要覆盖add()、remove()、getChild()方法,但是MenuItem就不应该有这些方法。这里给出的默认实现是抛出异常,你也可以根据自己的需要改写默认实现。
Menu类已经实现了除了getName方法的其他所有方法,因为Menu类具有添加菜单,移除菜单和获取子
菜单的功能。
//菜单 可以包含子菜单和菜单项
public class Menu extends MenuComponent {
//组合
private List<MenuComponent> menuComponentsList=new ArrayList<>();
public Menu(String name,int level){
this.level=level;
this.name=name;
}
@Override
public void add(MenuComponent menuComponent) {
menuComponentsList.add(menuComponent);
}
@Override
public void remove(MenuComponent menuComponent) {
menuComponentsList.remove(menuComponent);
}
@Override
public MenuComponent getChild(int i) {
return menuComponentsList.get(i);
}
@Override
public void print() {
for (int i = 0; i < level; i++) {
System.out.print("--");
}
System.out.println(name);
for (MenuComponent menuComponent : menuComponentsList) {
menuComponent.print();
}
}
}
MenuItem是菜单项,不能再有子菜单,所以添加菜单,移除菜单和获取子菜单的功能并不能实现。
//菜单项
public class MenuItem extends MenuComponent {
public MenuItem(String name,int level){
this.name=name;
this.level=level;
}
public void print() {
for (int i = 0; i < level; i++) {
System.out.print("--");
}
System.out.println(name);
}
}
public class Client {
public static void main(String[] args) {
MenuComponent menu1=new Menu("菜单管理",2);
menu1.add(new MenuItem("页面访问",3));
menu1.add(new MenuItem("展开菜单",3));
menu1.add(new MenuItem("编辑删除新增菜单",3));
MenuComponent menu2=new Menu("权限管理",2);
menu2.add(new MenuItem("页面提交",3));
menu2.add(new MenuItem("取消提交",3));
MenuComponent menu3=new Menu("角色管理",2);
menu3.add(new MenuItem("新增角色",3));
menu3.add(new MenuItem("删除角色",3));
//创建一级菜单
MenuComponent component=new Menu("系统管理",1);
component.add(menu1);
component.add(menu2);
component.add(menu3);
component.print();
}
}