结构型模式-组合模式

suaxi
2022-09-07 / 0 评论 / 53 阅读 / 正在检测是否收录...
(1)概述

组合模式又称为部分整体模式,是用于把一组相似的对象当作一个单一的对象,该模式依据树形结构来组合对象,用来表示部分以及整体层次

(2)结构
  • 抽象根节点:定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性
  • 树枝节点:定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成树结构
  • 叶子节点:其下再无分支,是系统层次遍历的最小单位
(3)案例

以树形菜单为例:

6.1组合模式(树形菜单案例-标准组合模式).png

抽象根节点

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()方法是没有意义的,在运行时调用由于未提供相应的错误处理代码而出错
  • 安全组合模式

    • 该模式中的抽象根节点角色未提供任何管理成员对象的方法,而是在树枝节点类中声明并实现这些方法,它的缺点是不够透明,因为叶子对象和容器对象具有不同的方法,容器对象中用于管理成员对象的方法没有在抽象根节点中定义,客户端不能实现相应的抽象编程,必须区别对待叶子对象和容器对象

      6.2组合模式(安全组合模式).png

(5)优缺点
  • 可以清楚定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,便于对整个层次结构的管理
  • 客户端可以一致的使用一个组合结构或其中的单个对象,无需关心处理的是单个对象还是整个组合结构
  • 新增/删除节点符合开闭原则
  • 通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但整个管理的过程并不复杂
(6)使用场景

多用于需要使用树形结构的场景

0

评论 (0)

取消