> 文章列表 > 组合设计模式

组合设计模式

组合设计模式

目录

前言:

 组合模式的原理与实现

总结:

参考资料:


前言:

    组合模式是一种比较容易混淆的设计模式,主要在于组合二字,我们知道有个设计原则组合优于继承,这里的组合和组合设计模式又不一样?


 组合模式的原理与实现

     组合模式就是将一组对象组织成树形结构,以表示一种“部分-整体”的层次结构。组合让客户端可以统一单个对象和组合对象的处理逻辑。

这样说可能会有些抽象,接下来我们举例进行说明。

假设我们有这样一个需求:设计一个类来表示文件系统中的目录,能方便地实现下面这些功能:

动态地添加、删除某个目录下的子目录或文件;

  • 统计指定目录下的文件个数;
  • 统计指定目录下的文件总大小。
  • 
    public class FileSystemNode {private String path;private boolean isFile;private List<FileSystemNode> subNodes = new ArrayList<>();public FileSystemNode(String path, boolean isFile) {this.path = path;this.isFile = isFile;}public int countNumOfFiles() {// TODO:...}public long countSizeOfFiles() {// TODO:...}public String getPath() {return path;}public void addSubNode(FileSystemNode fileOrDir) {subNodes.add(fileOrDir);}public void removeSubNode(FileSystemNode fileOrDir) {int size = subNodes.size();int i = 0;for (; i < size; ++i) {if (subNodes.get(i).getPath().equalsIgnoreCase(fileOrDir.getPath())) {break;}}if (i < size) {subNodes.remove(i);}}
    }

    如果我们将文件和目录进行区分设计,定义为filedirectrory两个类。

  • 
    public abstract class FileSystemNode {protected String path;public FileSystemNode(String path) {this.path = path;}public abstract int countNumOfFiles();public abstract long countSizeOfFiles();public String getPath() {return path;}
    }public class File extends FileSystemNode {public File(String path) {super(path);}@Overridepublic int countNumOfFiles() {return 1;}@Overridepublic long countSizeOfFiles() {java.io.File file = new java.io.File(path);if (!file.exists()) return 0;return file.length();}
    }public class Directory extends FileSystemNode {private List<FileSystemNode> subNodes = new ArrayList<>();public Directory(String path) {super(path);}@Overridepublic int countNumOfFiles() {int numOfFiles = 0;for (FileSystemNode fileOrDir : subNodes) {numOfFiles += fileOrDir.countNumOfFiles();}return numOfFiles;}@Overridepublic long countSizeOfFiles() {long sizeofFiles = 0;for (FileSystemNode fileOrDir : subNodes) {sizeofFiles += fileOrDir.countSizeOfFiles();}return sizeofFiles;}public void addSubNode(FileSystemNode fileOrDir) {subNodes.add(fileOrDir);}public void removeSubNode(FileSystemNode fileOrDir) {int size = subNodes.size();int i = 0;for (; i < size; ++i) {if (subNodes.get(i).getPath().equalsIgnoreCase(fileOrDir.getPath())) {break;}}if (i < size) {subNodes.remove(i);}}
    }

    使用代码如下:

  • 
    public class Demo {public static void main(String[] args) {/* /* /wz/* /wz/a.txt* /wz/b.txt* /wz/movies/* /wz/movies/c.avi* /xzg/* /xzg/docs/* /xzg/docs/d.txt*/Directory fileSystemTree = new Directory("/");Directory node_wz = new Directory("/wz/");Directory node_xzg = new Directory("/xzg/");fileSystemTree.addSubNode(node_wz);fileSystemTree.addSubNode(node_xzg);File node_wz_a = new File("/wz/a.txt");File node_wz_b = new File("/wz/b.txt");Directory node_wz_movies = new Directory("/wz/movies/");node_wz.addSubNode(node_wz_a);node_wz.addSubNode(node_wz_b);node_wz.addSubNode(node_wz_movies);File node_wz_movies_c = new File("/wz/movies/c.avi");node_wz_movies.addSubNode(node_wz_movies_c);Directory node_xzg_docs = new Directory("/xzg/docs/");node_xzg.addSubNode(node_xzg_docs);File node_xzg_docs_d = new File("/xzg/docs/d.txt");node_xzg_docs.addSubNode(node_xzg_docs_d);System.out.println("/ files num:" + fileSystemTree.countNumOfFiles());System.out.println("/wz/ files num:" + node_wz.countNumOfFiles());}
    }

    “将一组对象(员工和部门)组织成树形结构,以表示一种‘部分 - 整体’的层次结构(部门与子部门的嵌套结构)。组合模式让客户端可以统一单个对象(员工)和组合对象(部门)的处理逻辑(递归遍历)。

  • 总结:

       组合模式的设计思路,与其说是一种设计模式,倒不如说是对业务场景的一种数据结构和算法的 抽象。其中,数据可以表示成树这种数据结构,业务需求可以通过在树上的递归遍历算法来实现。

       组合模式,将一组对象组织成树形结构,将单个对象和组合对象都看做树中的节点,以统一处理逻辑,并且它利用树形结构的特点,递归地处理每个子树,依次简化代码实现。使用组合模式的前提在于,你的业务场景必须能够表示成树形结构。所以,组合模式的应用场景也比较局限,它并不是一种很常用的设计模式。

参考资料:

53 | 组合模式:如何设计实现支持递归遍历的文件系统目录树结构?-极客时间