【设计模式】通过简单案例学习组合模式

简介: 【设计模式】通过简单案例学习组合模式

组合模式


  组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。   可以通过一个或者多个简单的对象,经过组合之后,生成一个新的对象,原来的对象是这个对象的元素。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

  组合模式也可以看成是对某些对象的迭代调用的方式。

  组合模式优点:

  • 1、高层模块调用简单。
  • 2、节点自由增加。


案例分析


  下面通过一个大家都熟悉的示例,进行组合模式的初步理解。这个示例来源于往年的软考下午试题。

  如下图预构造一个文件目录树,就是我们常用的文件夹和文件的关系类似的。文件夹里面可以包含文件和文件夹,二层文件夹下又可以包含文件和文件夹。其中一层文件夹是二层文件夹和文件的父类;而三层文件夹或者文件又是二层文件夹的子类。类似这样的树状结构, 采用组合设计模式来设计。


image.png


分析


  性和动作,不管文件和文件夹,都有名称、大小、格式,都可以对文件和文件夹进行操作,包含修改、删除、移动等操作方式。那么可以将这些公共的操作和属性值提取出来一个抽象类。然后用一个子属性来代替下层数据信息。


开发


  可以从图中看到,针对公共属性和方法进行提取之后,可以创建一个AbstractFile的抽象类。其中包含:文件夹、文件的名称;添加文件或者文件夹的方法;删除文件或者文件夹的方法;移动文件或者文件夹的方法;获取文件子文件列表的方法。 AbstractFile的抽象类如下:


/**
 * @ClassName AbstractFile
 * @Description:
 * @Author 公众号:Java全栈架构师
 * @Version V1.0
 **/
public abstract class AbstractFile {
    protected String fileName;
    /**
     * 输出文件、文件夹名称
     * */
    public void printFileName(){
        System.out.println(fileName);
    }
    /**
     * 添加文件或者文件夹
     * */
    public abstract boolean addChild(AbstractFile abstractFile);
    /**
     * 删除文件或者文件夹
     * */
    public abstract boolean delChild(AbstractFile abstractFile);
    /**
     * 移动文件或者文件夹
     * */
    public abstract boolean removeChild(AbstractFile abstractFile);
    /**
     * 获取文件子文件列表
     * */
    public abstract List<AbstractFile> getChildAbstractFileList();
}

  

现在编写文件的具体实现类,因为文件没有子文件或文件夹,所以我们子啊获取文件子文件列表的时候,默认就返回null即可。这一点需要注意,和我们业务中的点一样,在编写代码实现的时候,对业务的基本流程和属性是需要一定了解的。其中在方法返回值之前,可以加入实际的业务逻辑,如果成功就返回true;如果处理失败,就返回false。系统会默认的返回false;


  文件File的类如下:


/**
 * @ClassName File
 * @Description:
 * @Author 公众号:Java全栈架构师
 * @Version V1.0
 **/
public class File extends AbstractFile {
    public File(String name){
        this.fileName = name;
    }
    @Override
    public boolean addChild(AbstractFile abstractFile) {
        return false;
    }
    @Override
    public boolean delChild(AbstractFile abstractFile) {
        return false;
    }
    @Override
    public boolean removeChild(AbstractFile abstractFile) {
        return false;
    }
    @Override
    public List<AbstractFile> getChildAbstractFileList() {
        return null;
    }
}

  

在创建文件夹的下的子文件或文件的集合的时候,需要注意去获取文件夹下的子文件和子文件夹下的文件和文件夹,需要层层迭代下去,本文作为示例,直接使用new 去创建了。这点需要注意。


  Folder文件夹的类如下:


/**
 * @ClassName Folder
 * @Description:
 * @Author 公众号:Java全栈架构师
 * @Version V1.0
 **/
public class Folder extends AbstractFile {
    private List<AbstractFile> list;
    public Folder(String name) {
        this.fileName = name;
        this.list = new ArrayList<AbstractFile>();
    }
    @Override
    public boolean addChild(AbstractFile abstractFile) {
        this.list.add(abstractFile);
        return false;
    }
    @Override
    public boolean delChild(AbstractFile abstractFile) {
        return false;
    }
    @Override
    public boolean removeChild(AbstractFile abstractFile) {
        return false;
    }
    @Override
    public List<AbstractFile> getChildAbstractFileList() {
        return list;
    }
}


运行


  以上基础模块已经搭建完成了,包含文件夹Folder和文件File两个。他们都有共同的方法。那么现在开始变写一下 遍历目录下的文件和文件夹名称的方法,输出文件名和文件夹名称。

  首先初始化模拟一个文件夹及文件的目录格式:其中根目录是:D:\,下面有几个文件夹分别为:“Linux”和“Win”两个,这两个文件夹下还有下层子集文件和文件夹。编写一个输出文件和文件夹名称的方法printFileTree,由于整个目录树都是基于文件夹Folder和文件File两个构建的,因此在输出过程中需要迭代使用printFileTree,具体方法如下:


/**
 * @ClassName Folder
 * @Description:
 * @Author 公众号:Java全栈架构师
 * @Version V1.0
 **/
public class MainApp {
    public static void main(String[] args) {
        AbstractFile rootFolder =new Folder("D:\\");
        AbstractFile linuxFolder =new Folder("Linux");
        AbstractFile winFolder =new Folder("Win");
        AbstractFile jdkFolder =new Folder("jdk");
        AbstractFile testFile =new File("test.java");
        AbstractFile linuxTestFile =new File("Linux_test.java");
        rootFolder.addChild(linuxFolder);
        rootFolder.addChild(winFolder);
        winFolder.addChild(jdkFolder);
        jdkFolder.addChild(testFile);
        linuxFolder.addChild(linuxTestFile);
        printFileTree(rootFolder);
    }
    public static void printFileTree(AbstractFile abstractFile) {
        abstractFile.printFileName();
        List<AbstractFile> abstractFileList = abstractFile.getChildAbstractFileList();
        if (abstractFileList == null) {
            return;
        } else {
            for (AbstractFile abstractFiles : abstractFileList) {
                printFileTree(abstractFiles);
            }
        }
    }
}

  

运行之后输出结果如下,可以看到文件目录的层级信息。


D:\
Linux
Linux_掘金.java
Win
jdk
test_掘金.java


image.png


结语


  好了,一个简单的组合模式就介绍完成了,学习设计模式的时候,尽量结合熟悉的案例进行分析,这样的话就会有事半功倍的奇效,也更容易理解。大家可以尝试着在项目中使用设计模式的方式进行开发。



目录
相关文章
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
4月前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 组合模式
js设计模式【详解】—— 组合模式
52 7
|
2月前
|
设计模式 Java
Java设计模式:组合模式的介绍及代码演示
组合模式是一种结构型设计模式,用于将多个对象组织成树形结构,并统一处理所有对象。例如,统计公司总人数时,可先统计各部门人数再求和。该模式包括一个通用接口、表示节点的类及其实现类。通过树形结构和节点的通用方法,组合模式使程序更易扩展和维护。
Java设计模式:组合模式的介绍及代码演示
|
2月前
|
设计模式 存储 安全
Java设计模式-组合模式(13)
Java设计模式-组合模式(13)
|
3月前
|
设计模式 Java
常用设计模式介绍~~~ Java实现 【概念+案例+代码】
文章提供了一份常用设计模式的全面介绍,包括创建型模式、结构型模式和行为型模式。每种设计模式都有详细的概念讲解、案例说明、代码实例以及运行截图。作者通过这些模式的介绍,旨在帮助读者更好地理解源码、编写更优雅的代码,并进行系统重构。同时,文章还提供了GitHub上的源码地址,方便读者直接访问和学习。
常用设计模式介绍~~~ Java实现 【概念+案例+代码】
|
5月前
|
设计模式 存储 算法
设计模式学习心得之五种创建者模式(2)
设计模式学习心得之五种创建者模式(2)
45 2
|
5月前
|
设计模式 uml
设计模式学习心得之前置知识 UML图看法与六大原则(下)
设计模式学习心得之前置知识 UML图看法与六大原则(下)
42 2
|
5月前
|
设计模式 存储 安全
Java设计模式:组合模式之透明与安全的两种实现(七)
Java设计模式:组合模式之透明与安全的两种实现(七)
|
5月前
|
设计模式 Java
Java设计模式之组合模式详解
Java设计模式之组合模式详解
|
5月前
|
设计模式 安全 Java
设计模式学习心得之五种创建者模式(1)
设计模式学习心得之五种创建者模式(1)
38 0