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

一.意图

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

  • 文件夹下,可以包括文件、文件夹
  • 文件就不能进行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)


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

正确答案

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

相关推荐
屋外雨大,惊蛰出没7 天前
组合模式(composite)
组合模式
石逸凡20 天前
论组织本源与钻形式招牌的空子
大数据·组合模式
c++之路25 天前
组合模式(Composite Pattern)
组合模式
likerhood1 个月前
设计模式 · 组合模式(Composite Pattern)
设计模式·组合模式
蜡笔小马1 个月前
07.C++设计模式-组合模式
c++·设计模式·组合模式
多加点辣也没关系1 个月前
设计模式-组合模式
设计模式·组合模式
qq_296553271 个月前
[特殊字符] 数组中的递增三元组:O(n) 时间高效查找,面试必考!
数据结构·算法·面试·职场和发展·组合模式·柔性数组
geovindu2 个月前
go: Composite Pattern
设计模式·golang·组合模式
ximu_polaris2 个月前
设计模式(C++)-结构型模式-组合模式
c++·设计模式·组合模式