(1)概述
组合模式又称为部分整体模式,是用于把一组相似的对象当作一个单一的对象,该模式依据树形结构来组合对象,用来表示部分以及整体层次
(2)结构
- 抽象根节点:定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性
- 树枝节点:定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成树结构
- 叶子节点:其下再无分支,是系统层次遍历的最小单位
(3)案例
以树形菜单为例:
抽象根节点
public abstract class MenuComponent {
protected String name;
protected int level;
/**
* 添加菜单
*
* @param menuComponent
*/
public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
/**
* 移除菜单
*
* @param menuComponent
*/
public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
/**
* 查询子菜单
*
* @param index
* @return
*/
public MenuComponent getChild(int index) {
throw new UnsupportedOperationException();
}
/**
* 查询菜单或菜单项的名称
*
* @return
*/
public String getName() {
return name;
}
/**
* 打印菜单(包含子菜单和子菜单项)
*/
public abstract void print();
}
树枝节点
public class Menu extends MenuComponent {
private List<MenuComponent> menuComponentList = new ArrayList<>();
public Menu(String name, int level) {
this.name = name;
this.level = level;
}
@Override
public void add(MenuComponent menuComponent) {
menuComponentList.add(menuComponent);
}
@Override
public void remove(MenuComponent menuComponent) {
menuComponentList.remove(menuComponent);
}
@Override
public MenuComponent getChild(int index) {
return menuComponentList.get(index);
}
@Override
public void print() {
for (int i = 0; i < level; i++) {
System.out.print(" ");
}
//打印菜单名称
System.out.println(name);
//打印子菜单/子菜单项名称
for (MenuComponent menuComponent : menuComponentList) {
menuComponent.print();
}
}
}
public class MenuItem extends MenuComponent {
public MenuItem(String name, int level) {
this.name = name;
this.level = level;
}
@Override
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 menue1 = new Menu("菜单一", 2);
menue1.add(new MenuItem("1", 3));
menue1.add(new MenuItem("2", 3));
menue1.add(new MenuItem("3", 3));
MenuComponent menue2 = new Menu("菜单二", 2);
menue2.add(new MenuItem("1", 3));
menue2.add(new MenuItem("2", 3));
menue2.add(new MenuItem("3", 3));
MenuComponent menue3 = new Menu("菜单三", 2);
menue3.add(new MenuItem("1", 3));
menue3.add(new MenuItem("2", 3));
menue3.add(new MenuItem("3", 3));
MenuComponent menue4 = new Menu("菜单四", 2);
menue4.add(new MenuItem("1", 3));
menue4.add(new MenuItem("2", 3));
menue4.add(new MenuItem("3", 3));
//将二级菜单添加到一级菜单中
MenuComponent component = new Menu("根菜单", 1);
component.add(menue1);
component.add(menue2);
component.add(menue3);
component.add(menue4);
//打印菜单
component.print();
}
}
(4)分类
透明组合模式
- 在该模式中,抽象根节点角色声明了所有用于管理成员对象的方法,以此确保所有的构建类都有相同的接口,即标准组合模式
- 该模式不够安全,因为叶子对象和容器对象有着本质上的区别,叶子对象不可能有下级节点(即不包含成员对象)因此提供的
add()
、remove()
方法是没有意义的,在运行时调用由于未提供相应的错误处理代码而出错
安全组合模式
该模式中的抽象根节点角色未提供任何管理成员对象的方法,而是在树枝节点类中声明并实现这些方法,它的缺点是不够透明,因为叶子对象和容器对象具有不同的方法,容器对象中用于管理成员对象的方法没有在抽象根节点中定义,客户端不能实现相应的抽象编程,必须区别对待叶子对象和容器对象
(5)优缺点
- 可以清楚定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,便于对整个层次结构的管理
- 客户端可以一致的使用一个组合结构或其中的单个对象,无需关心处理的是单个对象还是整个组合结构
- 新增/删除节点符合开闭原则
- 通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但整个管理的过程并不复杂
(6)使用场景
多用于需要使用树形结构的场景
评论 (0)