结构型设计模式-组合模式

Posted vbirdbest

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结构型设计模式-组合模式相关的知识,希望对你有一定的参考价值。

一:定义

组合设计模式: 又名部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分还是整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

二:透明组合模式案例

需求:打印某个菜单下的所有菜单名字及菜单项的名字。

MenuComponent:抽取菜单和菜单项的公共属性和方法,如果某类不支持某个操作就抛出不支持异常,如果支持就子类去实现即可。这样客户端无论在使用菜单还是在使用菜单项时,都是使用的同一套方法,只是有些方法在不同的类中是不支持的。

/**
 * 菜单组件(抽象根节点)
 */
public abstract class MenuComponent 
    /** 菜单名称 */
    protected String name;
    /** 菜单层级 */
    protected Integer level;

    // 添加子菜单(菜单是可以添加的,菜单项是不可以添加的)
    public void add(MenuComponent menComponent) 
        throw new UnsupportedOperationException();
    

    // 移除子菜单(菜单是可以移除的,菜单项是不可以移除的)
    public void remove(MenuComponent menComponent) 
        throw new UnsupportedOperationException();
    

    // 获取指定的子菜单(菜单是可以获取子菜单的,菜单项是不可以获取的)
    public MenuComponent getChild(int i) 
        throw new UnsupportedOperationException();
    

    public String getName() 
        return name;
    

    // 打印菜单名称的方法
    public abstract void print();

/**
 * 菜单类(树枝节点)
 */
public class Menu extends MenuComponent 
    /** 菜单可以有多个子菜单或者子菜单项 */
    private List<MenuComponent> children = new ArrayList<>();

    public Menu(String name, int level) 
        this.name = name;
        this.level = level;
    


    @Override
    public void add(MenuComponent menComponent) 
        children.add(menComponent);
    

    @Override
    public void remove(MenuComponent menComponent) 
        children.remove(menComponent);
    

    @Override
    public MenuComponent getChild(int i) 
        return children.get(i);
    

    @Override
    public void print() 
        for (int i = 1; i < this.level; i++) 
            System.out.print("\\t");
        

        // 打印当前菜单名称
        System.out.println(this.name);
        // 打印子菜单或者子菜单项

        for (MenuComponent menuComponent : children) 
            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 = 1; i < this.level; i++) 
            System.out.print("\\t");
        

        // 直接打印菜单项的名称
        System.out.println(this.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));
        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));
        menu3.add(new MenuItem("修改角色", 3));

        MenuComponent systemMenu = new Menu("系统管理", 1);
        systemMenu.add(menu1);
        systemMenu.add(menu2);
        systemMenu.add(menu3);

        systemMenu.print();
    

三:优点

  • 组合模式可以清楚的定义分层次的复杂对象,表示对象的全部或者部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。

  • 客户端可以一致的使用组合结构或其中单个对象,不必关系处理的是的那个对象还是整个组合结构,简化了客户端代码。

  • 在组合模式中增加新的树枝节点和叶子节点都很方便,无需对现有类库进行任何修改,符合开闭原则。

  • 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但树形结构的控制却非常简单。

四:使用场景

组合模式是应树形结构而生的,所以组合模式的使用场景就是出现树形结构的地方。比如:文件目录显示,多级目录呈现等树形结构数据的操作。

以上是关于结构型设计模式-组合模式的主要内容,如果未能解决你的问题,请参考以下文章

组合模式(18)

设计模式--组合模式

Java 设计模式之组合学习与掌握

Java 设计模式之组合学习与掌握

设计模式--组合模式C++实现

结构型模式之组合模式