设计模式-组合模式(部分整体模式)

本文介绍了组合模式在文件系统中的应用,通过抽象根节点、树枝节点和叶子节点实现对象的树形结构。文件夹作为树枝节点,包含其他文件夹或文件(叶子节点)。使用组合模式,可以将目录和文件视为同一类型进行操作,如遍历。代码示例展示了如何创建和打印菜单结构,文件夹类实现了添加、删除和获取子菜单的方法,而文件类则不支持这些操作,调用时会抛出异常。组合模式提高了代码复用性和操作一致性。
摘要由CSDN通过智能技术生成

模式意图

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

比如文件系统,目录包含目录或者文件,目录和文件是两个对象,但这种树形结构将各个结点看作是一个对象更好操作,如遍历等,如何将目录和文件看作是同一对象来操作?

模式结构

抽象跟结点:定义系统各层次对象的共有方法和属性

树枝结点:存储叶子结点,并且和叶子结点共同组成树形结构,如文件夹对象

叶子结点:叶子结点对象,再无分支,如文件对象

文件系统案例

有三部分结构

MenuComponent

抽象类,由Menu和Menuitem继承,负责将不同类对象相同对待,并且定义二者的相同方法和属性来提高代码的复用。

每个文件或者文件夹都有名称和等级,并且有添加(add),移除(remove),获取(getChild)子菜单的方法和打印(print)菜单或者文件信息的方法。

Menu

菜单类,指文件夹,每个文件夹中有个集合,来存储文件夹或者文件

Menuitem

菜单项类,指文件

package mode;

import java.util.ArrayList;
import java.util.List;

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 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;
    }
    @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();
        }
    }
}

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);
    }
}

在Client先创建一级文件,一级文件的文件集合中添加多个二级菜单,二级菜单中添加多个文件。

通过一级菜单对象打印整体结构。文件夹的print方法先打印自身,再打印集合,文件的print方法只打印自身

为什么抛出异常

 上例中为什么文件中很多方法用不到还要在抽象类中定义,就是为了操作不同对象时可以调用相同接口,文件夹类调用add,remove方法会调用该类的重写方法,而文件类调用时,会调用父类中的,会抛出错误。

优点

 

使用场景

组合结构应树形结构而生,多用于出现树型结构的场景

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值