在前面的博文中,小编介绍了三个工厂模式,三世同堂,各司其职,各有千秋,今天我们继续来学习设计模式的相关知识,今天这篇博文,我们继续来学习设计模式的相关知识,今天这篇博文小编主要和小伙伴们来学习组合模式。小编会从什么是组合模式、组合模式的结构图、组合模式的角色和职责以及结合相关的deom来进行讲解。
一、什么是组合模式
组合模式,英文名字叫Composite,是结构型的设计模式,通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
二、组合模式的结构图
三、组合模式的角色和职责
Component(树形结构的节点抽象)
为所有的对象定义统一的接口(公共属性,行为等的定义)
提供管理子节点对象的接口方法
[可选]提供管理父节点对象的接口方法
Leaf(树形结构的叶结点)
Component的实现子类
Composite(树形结构的枝节点)
Component的实现子类
接着,小编举一个简单的例子,小伙伴们看下面这幅图
上面两幅图片我们可以看作是一个文件结构,对于这样的结构我们称之为树形结构,在程杰老师的大话设计模式一书中,我们知道可以通过调用某个方法来遍历整棵树,当我们找到某个叶子节点后,就可以对叶子节点进行相关的操作,我们可以将这棵树理解成一个大容器,容器里面包含很多的成员对象,这些成员对象既可以是容器对象也可以是叶子对象,但是由于容器对象和叶子对象在功能上面的区别,使得我们在使用的过程中要区分容器对象和叶子对象,但是这样会给用户带来不必要的麻烦,对于客户而言,始终希望能够一致的对待容器对象和叶子对象,这就是组合模式的设计动机,组合模式定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一直的处理。接着小编通过一个简单的demo讲解组合模式如何在项目中使用,希望可以帮助到有需要的小伙伴,不足之处,还请小伙伴多多指教`(*∩_∩*)′。
四、组合模式小demo
新建项目Composite项目,新建接口IFile也就是文件节点的抽象相当于设计模式结构图中的Component,编写相关代码,如下所示:
import java.util.List; /** * 文件节点抽象(是文件和目录的父类) * @author Flower * */ public interface IFile { //显示文件或文件夹的名称 public void display(); //添加 public boolean add(IFile file); //移除 public boolean remove(IFile file); //获得子节点 public List<IFile> geChild(); }
接着新建File,相当于结构图中的Leaf,具体代码如下所示:
import java.util.List; public class File implements IFile { private String name; public File (String name){ this.name = name; } @Override public void display() { // TODO Auto-generated method stub } @Override public boolean add(IFile file) { // TODO Auto-generated method stub return false; } @Override public boolean remove(IFile file) { // TODO Auto-generated method stub return false; } @Override public List<IFile> geChild() { // TODO Auto-generated method stub return null; } }
新建类Folder,相当于结构图中的Composite,编写相关的代码部分,如下所示:
import java.util.ArrayList; import java.util.List; public class Folder implements IFile { private String name; private List<IFile> children; public Folder(String name){ this.name = name; children= new ArrayList<IFile>(); } @Override public void display() { System.out.println(name); } @Override public boolean add(IFile file) { return children.add(file); } @Override public boolean remove(IFile file) { return children.remove(file); } @Override public List<IFile> geChild() { return children; } }
编写客户端的代码,新建类MainClass,具体代码如下所示:
import java.util.List; public class MainClass { public static void main(String[] args){ //C盘 Folder rootFolder = new Folder("C:"); //beifeng目录 Folder beifengFolder = new Folder("beifeng"); //beifeng.txt文件 File beifengFile = new File("beifeng.txt"); rootFolder.add(beifengFile); rootFolder.remove(beifengFile); displayTree(rootFolder); } private static void displayTree(IFile rootFolder) { rootFolder.display(); List<IFile> children = rootFolder.geChild(); //遍历子数 for(IFile file:children){ if(file instanceof File){ file.display(); }else{ displayTree(file); } } } }
运行,如下所示:
小伙伴们可能觉得这样看起来层次结构不是很清晰,我们来完善一下我们的MainClass部分,如下所示:
import java.util.List; public class MainClass { public static void main(String[] args){ //C盘 Folder rootFolder = new Folder("C:"); //beifeng目录 Folder beifengFolder = new Folder("beifeng"); //beifeng.txt文件 File beifengFile = new File("beifeng.txt"); rootFolder.add(beifengFolder); rootFolder.add(beifengFile); //ibeifeng目录 Folder ibeifengFolder = new Folder("ibeifeng"); File ibeifengFile = new File("ibeifeng.txt"); beifengFolder.add(ibeifengFolder); beifengFolder.add(ibeifengFile); displayTree(rootFolder); } private static void displayTree(IFile rootFolder) { //显示自身的名称 rootFolder.display(); //获得子树 List<IFile> children = rootFolder.geChild(); //遍历子数 for(IFile file : children){ if(file instanceof File){ file.display(); }else{ displayTree(file); } } } }
运行一下,效果如下所示:
这样层次结构就比较深了,接着我们加上层次结构,完善MainClass的代码部分,如下所示:
import java.util.List; public class MainClass { public static void main(String[] args){ //C盘 Folder rootFolder = new Folder("C:"); //beifeng目录 Folder beifengFolder = new Folder("beifeng"); //beifeng.txt文件 File beifengFile = new File("beifeng.txt"); rootFolder.add(beifengFolder); rootFolder.add(beifengFile); //ibeifeng目录 Folder ibeifengFolder = new Folder("ibeifeng"); File ibeifengFile = new File("ibeifeng.txt"); beifengFolder.add(ibeifengFolder); beifengFolder.add(ibeifengFile); displayTree(rootFolder,0); } private static void displayTree(IFile rootFolder,int deep) { for(int i = 0;i<deep;i++){ System.out.println("--"); } //显示自身的名称 rootFolder.display(); //获得子树 List<IFile> children = rootFolder.geChild(); //遍历子数 for(IFile file : children){ if(file instanceof File){ for(int i =0;i<deep;i++){ System.out.println("--"); } file.display(); }else{ displayTree(file,deep+1); } } } }
运行效果如下所示:
我们再来添加一个,完善代码,如下所示:
import java.util.List; public class MainClass { public static void main(String[] args){ //C盘 Folder rootFolder = new Folder("C:"); //beifeng目录 Folder beifengFolder = new Folder("beifeng"); //beifeng.txt文件 File beifengFile = new File("beifeng.txt"); rootFolder.add(beifengFolder); rootFolder.add(beifengFile); //ibeifeng目录 Folder ibeifengFolder = new Folder("ibeifeng"); File ibeifengFile = new File("ibeifeng.txt"); beifengFolder.add(ibeifengFolder); beifengFolder.add(ibeifengFile); Folder iibeifengFolder = new Folder("iibeifeng"); File iibeifengFile = new File("iibeifeng.txt"); ibeifengFolder.add(iibeifengFolder); ibeifengFolder.add(iibeifengFile); displayTree(rootFolder,0); } private static void displayTree(IFile rootFolder,int deep) { for(int i = 0; i < deep; i++) { System.out.print("--"); } //显示自身的名称 rootFolder.display(); //获得子树 List<IFile> children = rootFolder.geChild(); //遍历子数 for(IFile file : children){ if(file instanceof File){ for(int i = 0; i <= deep; i++) { System.out.print("--"); } file.display(); }else{ displayTree(file,deep+1); } } } }
运行效果,如下所示:
小编寄语:该博文小编主要简单的介绍了设计模式中组合模式的相关知识,对于设计模式的演练,仅仅掌握理论知识是远远不够的,人类智慧的结晶还是需要我们在大量的实战中去慢慢体会,慢慢去锤炼,总的来说,组合模式呢,将对象组合成树形结构以表示部分和整体的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式。小伙伴们可以结合日常生活中的系统目录结构和网站导航结构帮助理解`(*∩_∩*)′。