什么是组合模式?一文详解

一.意图

将对象组合成树型结构,以表示"部分-整体"的层次结构。组合模式使得用户对单个对象(文件,由于文件是最底层,没儿子,所以叫"单个对象")和组合对象(文件夹,文件夹有儿子,所以叫"组合对象")的使用具有一致性(一致性的意思是,无论是文件还是文件夹,我们创建对象时,左面的声明类型都用抽象文件表示,这是一种多态的思想,很多算法都用到了)。
核心思想:

  • 文件夹下,可以包括文件、文件夹
  • 文件就不能进行add、和remove方法了(说白了,到文件就结束了,它不可能在下面继续深入添加儿子了,因为文件就到底了。再说白了,只有文件夹才能继续添加儿子)因此具体的做法就是(首先要知道,文件作为抽象文件的子类,是一定要实现抽象文件的add和remove方法,但是文件还不能进行add和remove,因此实现add和remove方法时,直接return "文件无法执行add、remove操作"之类的特殊处理信息即可。或者add和remove的返回值类型是boolean类型,那我们直接令文件的add和remove操作的返回值都是false即可,表示文件不能进行添加、删除儿子,因为文件就是最底层,没有儿子。)

二.结构

三.举例:文件夹、文件的树状结构(操作系统的目录结构)

1.代码

①创建"抽象文件"

java 复制代码
//抽象文件(即:可以是文件夹,也可以是文件,故称为"抽象文件")
public abstract class AbstractFile {
    protected String name;//抽象文件的名称(即:文件夹的名称 / 文件的名称)
    //打印抽象文件的名称
    public void printName(){
        System.out.println(name);
    }

    //添加抽象文件(true代表添加成功、false代表添加失败)
    public abstract boolean add(AbstractFile file);
    //移除抽象文件(true代表移除成功、false代表移除失败)
    public abstract boolean remove(AbstractFile file);
    //获取子抽象文件组(儿子/子组件)
    public abstract List<AbstractFile> getChildren();
}

②创建"文件夹"

java 复制代码
//文件夹
public class Folder extends AbstractFile{
    //当前文件夹的子抽象文件组(儿子/子组件)
    private List<AbstractFile> childrenList = new ArrayList<AbstractFile>();

    public Folder(String name){
        this.name = name;
    }

    @Override
    public boolean add(AbstractFile file) {
        return childrenList.add(file);
    }

    @Override
    public boolean remove(AbstractFile file) {
        return childrenList.remove(file);
    }

    @Override
    public List<AbstractFile> getChildren() {
        return childrenList;
    }
}

③创建"文件"

java 复制代码
//文件
public class File extends AbstractFile{
    public File(String name){
        this.name = name;
    }

    @Override
    public boolean add(AbstractFile file) {
        return false;//文件就是最底层了,不能添加儿子,所以恒为false
    }

    @Override
    public boolean remove(AbstractFile file) {
        return false;//文件就是最底层了,不能移除儿子,所以恒为false
    }

    @Override
    public List<AbstractFile> getChildren() {
        return null;//文件就是最底层,根本不可能有儿子,所以返回null
    }

}

测试一下

java 复制代码
public class Demo01Application {
    //输出整体的树状结构
    static void print(AbstractFile file){
        //先输出自己的名字
        file.printName();
        //获取儿子集合
        List<AbstractFile> childrenList = file.getChildren();
        if(childrenList == null) return;
        //遍历每个儿子
        for(AbstractFile children: childrenList){
            //递归调用本方法
            print(children);//这里要用递归,这也是一个考点
        }
    }
    public static void main(String[] args) {
        AbstractFile root = new Folder("root");
        AbstractFile folderA = new Folder("folderA");
        AbstractFile folderB = new Folder("folderB");

        AbstractFile fileC = new File("fileC");
        AbstractFile fileD = new File("fileD");
        AbstractFile fileE = new File("fileE");

        root.add(folderA);
        root.add(folderB);
        root.add(fileC);

        folderA.add(fileD);
        folderA.add(fileE);

        //输出树状结构
        print(root);
    }


}

我们可以先根据常识,画一下目前代码中的目录结构:

所以此时遍历输出的结果顺序(先序遍历,即:根、左、右)应该是:

root、folderA、fileD、fileE、folderB、fileC

四.软考真题

1.2009年下半年

题目

分析过程

(1)abstract

(2)null

(3)List

(4)childList

(5)printTree(file)


没啥好说的,和我们上述举的例子一模一样。

正确答案

将我们上述的答案,和下面的正确答案进行对比,发现全对了。

2.2010年下半年

题目

分析过程

(1)abstract class

注意别把class丢了

(2)this.name

(3)Company

(4)Company

(5)children

(6)children

(7)root.Add(comp)

(8)comp.Add(comp1)


这题和文件、文件夹哪个类型的题一样,都是很简单的。

正确答案

将我们上述的答案,和下面的正确答案对比,发现全对了

相关推荐
c++之路4 天前
组合模式(Composite Pattern)
组合模式
likerhood8 天前
设计模式 · 组合模式(Composite Pattern)
设计模式·组合模式
蜡笔小马10 天前
07.C++设计模式-组合模式
c++·设计模式·组合模式
多加点辣也没关系11 天前
设计模式-组合模式
设计模式·组合模式
qq_2965532715 天前
[特殊字符] 数组中的递增三元组:O(n) 时间高效查找,面试必考!
数据结构·算法·面试·职场和发展·组合模式·柔性数组
geovindu1 个月前
go: Composite Pattern
设计模式·golang·组合模式
ximu_polaris1 个月前
设计模式(C++)-结构型模式-组合模式
c++·设计模式·组合模式
yaaakaaang1 个月前
八、组合模式
组合模式
无籽西瓜a2 个月前
【西瓜带你学设计模式 | 第十三期 - 组合模式】组合模式 —— 树形结构统一处理实现、优缺点与适用场景
java·后端·设计模式·组合模式·软件工程