叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。
基本概念:
组合模式[构造性设计模式]定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一致的处理。
组合模式的角色:
- Component :组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
- Leaf:叶子对象。叶子结点没有子结点。
- Composite:容器对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
组合模式优点和缺点:
1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。
2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。
缺点:
使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联
首先定义个接口,包含叶子和容器的特性的抽象方法:文件夹为容器,为
Composite,容器对象;文件为
Leaf,叶子节点;IFile,
Component ,组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为.
-
/* * 文件节点抽象(是文件和目录的父类) */ public interface IFile { //显示文件或者文件夹的名称 public void display(); //添加 public boolean add(IFile file); //移除 public boolean remove(IFile file); //获得子节点 public List<IFile> getChild(); }
IFile实现类:文件夹类Folder.java,容器对象,里面可添加文件,删除文件;
-
import java.util.ArrayList; import java.util.List; /** * 文件夹类 * @author soyoungboy * */ public class Folder implements IFile{ private String name; private List<IFile> children; public Folder(String name) { this.name = name; children = new ArrayList<IFile>(); } /** * 显示文件夹名称 */ public void display() { System.out.println(name); } /** * 文件夹下可能有文件,故显示 */ public List<IFile> getChild() { return children; } /** * 文件夹下面添加文件 */ public boolean add(IFile file) { return children.add(file); } /** * 文件夹下面删除文件 */ public boolean remove(IFile file) { return children.remove(file); } }
- IFile实现类:子节点,File.java
-
import java.util.List; /** * 文件类,无子节点,故无getChild返回内容,文件下不可条件文件,不可删除文件,故add,remove为false * @author soyoungboy * */ public class File implements IFile { private String name; public File(String name) { this.name = name; } /** * 文件显示 */ public void display() { System.out.println(name); } /** * 文件下面没有文件 */ public List<IFile> getChild() { return null; } /** * 添加文件 */ public boolean add(IFile file) { return false; } /** * 删除文件 */ public boolean remove(IFile file) { return false; } }
测试类:
import java.util.List; public class MainClass { public static void main(String[] args) { //C盘 Folder rootFolder = new Folder("C:"); //first目录 Folder firstFolder = new Folder("first"); //first.txt文件 File firstFile = new File("first.txt"); rootFolder.add(firstFolder); rootFolder.add(firstFile); //second目录 Folder secondFolder = new Folder("second"); File secondFile = new File("second.txt"); //添加二级目录 firstFolder.add(secondFolder); //二级目录中添加文件second.txt firstFolder.add(secondFile); Folder thirdFolder = new Folder("third"); File thirdFile = new File("third.txt"); //添加三级目录 secondFolder.add(thirdFolder); //添加三级文件third.txt secondFolder.add(thirdFile); displayTree(rootFolder,0); } public static void displayTree(IFile rootFolder, int deep) { for(int i = 0; i < deep; i++) { System.out.print("--"); } //显示自身的名称 rootFolder.display(); //获得子树 List<IFile> children = rootFolder.getChild(); //遍历子树 for(IFile file : children) { //如果是文件的话 if(file instanceof File) { for(int i = 0; i <= deep; i++) { System.out.print("--"); } //直接调用display操作 file.display(); } else { //如果是目录的话,递归操作 displayTree(file,deep + 1); } } } }
C:
--first
----second
------third
------third.txt
----second.txt
--first.txt
android中的使用场景:
一般处理树形结构的内容。
ViewGroup和View的结构就是一个组合模式: