组合模式

       组合(Composite Pattern)模式(整体-部分(Part-Whole)模式),是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。

       组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点,树形结构图如下

       

 

        根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用;而叶子节点与树枝节点在语义上不属于用一种类型。但是在组合模式中,会把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让它们具备一致行为。

组合模式优点:

  1. 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
  2. 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;

其主要缺点是:

  1. 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
  2. 不容易限制容器中的构件;
  3. 不容易用继承的方法来增加构件的新功能;

组合模式的结构

  1. 抽象构件(Component)角色:作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
  2. 树叶构件(Leaf)角色:是组合中的叶节点对象,没有子节点,用于继承或实现抽象构件。
  3. 树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

         

public abstract class MenuComponent {

    protected String name;
    protected int level;

    public void add(MenuComponent component) {
        throw new UnsupportedOperationException();
    }

    public void remove(MenuComponent component) {
        throw new UnsupportedOperationException();
    }

    public MenuComponent getChild(int i) {
        throw new UnsupportedOperationException();
    }

    public String getName() {
        return name;
    }

    public void print() {
        throw new UnsupportedOperationException();
    }
}

       Menu类实现了除getName方法的其他所有方法,因为Menu类具有添加菜单,移除菜单和获取子菜单的功能

public class Menu extends MenuComponent {

    private List<MenuComponent> menuComponentList = new ArrayList<>();

    public Menu(String name, int level) {
        this.name = name;
        this.level = level;
        this.menuComponentList = new ArrayList<>();
    }

    @Override
    public void add(MenuComponent component) {
        menuComponentList.add(component);
    }

    @Override
    public void remove(MenuComponent component) {
        menuComponentList.remove(component);
    }

    @Override
    public MenuComponent getChild(int i) {
        return menuComponentList.get(i);
    }

    @Override
    public void print() {
        for (int i = 0; i < level; i++) {
            System.out.println("--");
        }
        System.out.println(name);
        for (MenuComponent component : menuComponentList) {
            component.print();
        }
    }
}

  MenuItem是菜单项,不能再有子菜单,所以添加菜单,移除菜单和获取子菜单的功能并不能实现。

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.println("--");
        }
        System.out.println(name);
    }
}

  测试类

public class MenuTest {
    public static void main(String[] args) {
        MenuComponent systemManager = new Menu("系统管理", 0);

        MenuComponent menuManager = new Menu("菜单管理", 1);
        MenuItem view = new MenuItem("查看", 2);
        MenuItem edit = new MenuItem("编辑", 2);
        menuManager.add(view);
        menuManager.add(edit);
        systemManager.add(menuManager);

        MenuComponent permissionManager = new Menu("权限管理", 1);
        MenuItem add = new MenuItem("添加权限", 2);
        MenuItem remove = new MenuItem("移除权限", 2);
        permissionManager.add(add);
        permissionManager.add(remove);
        systemManager.add(permissionManager);

        MenuComponent soleManager = new Menu("角色管理", 1);
        MenuItem addSole = new MenuItem("添加角色", 2);
        soleManager.add(addSole);
        MenuItem editSole = new MenuItem("编辑角色", 2);
        soleManager.add(editSole);
        systemManager.add(soleManager);

        systemManager.print();
    }
}

 

         

posted on 2022-04-04 10:12  溪水静幽  阅读(54)  评论(0)    收藏  举报