23种设计模式之组合模式

x33g5p2x  于2022-03-22 转载在 其他  
字(2.8k)|赞(0)|评价(0)|浏览(446)

组合模式

组合模式(Composite Pattern),又叫部分整体模式。它创建了对象组的树形结构,将对象组合成树状结构以表示整体-部分的层次关系。组合模式能让客户端以一致的方式处理个别对象以及组合对象。组合模式主要包括以下主要角色:

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

【案例】

我们在访问一些管理系统时,可以看到类似的菜单。一个菜单可以包含菜单项(不再包含其他内容的菜单条目)也可以包含带有其他菜单项的菜单,因此使用组合模式描述菜单就很恰当。请设计程序打印菜单内的所有菜单和菜单项

public class CompositeTest { //客户端
    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));
        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();
    }
}
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 index){
        throw new UnsupportedOperationException();
    }
    //获取菜单或者菜单项的名字
    public String getName(){
        return name;
    }
    //打印菜单名称
    public abstract void print();
}
class Menu extends MenuComponent{ //树枝结点
    //菜单可以有多个子菜单或子菜单项
    private List<MenuComponent> menuComponentList = new ArrayList<>();
    public Menu(String name,int level){
        this.name = name;
        this.level = level;
    }
    public void add(MenuComponent menuComponent) {
        menuComponentList.add(menuComponent);
    }
    public void remove(MenuComponent menuComponent) {
        menuComponentList.remove(menuComponent);
    }
    public MenuComponent getChild(int index) {
        return menuComponentList.get(index);
    }
    public void print() {
        for (int i = 1; i < level; i++) {System.out.print("--");}
        System.out.println(name);
        for (MenuComponent menuComponent : menuComponentList) {
            menuComponent.print();
        }
    }
}
class MenuItem extends MenuComponent{//叶子结点
    public MenuItem(String name,int level){
        this.name = name;
        this.level = level;
    }
    public void print() {
        for (int i = 1; i < level; i++) {System.out.print("--");}
        System.out.println(name);
    }

}

【运行结果】

系统管理
--菜单管理
----展开菜单
----编辑菜单
----删除菜单
----新增菜单
--权限管理
----页面访问
----提交保存
--角色管理
----新增角色
----修改角色

Process finished with exit code 0

组合模式的优缺点

  • 优点
    1、组合模式可以清除地定义分层次的复杂对象,表示对象的部分层次。它可以让客户端忽略了层次的差异,方便对整个层次结构进行控制
    2、客户端可以一致地使用一个组合结构或者其中的单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码
    3、在组合模式中添加新的树枝结点和叶子结点都很方便,无需对类库进行修改,符合开闭原则
  • 缺点
    1、设计较复杂
    2、不容易用继承的方法来增加构件的新功能;

使用场景

组合模式正是应树形结构而生,所以组合模式的使用场景就是出现树形结构的地方。比如文件目录显示。在 JAVA的AWT 和 SWING 中也使用了组合模式,对于 Button 和 Checkbox 是树叶,Container 是树枝。

相关文章