总结:
1.组合模式适用于对树形结构的操作,比如递归检查每一个权限树、递归删除权限树等
2.抽象子节点时,比如例子1中 叶子结点(文件)和非叶子结点(目录)是有不一致的行为的,比如文件不能添加目录,像这种情况就要声明一个接口,1个叶子结点实现类和1个非叶子结点实现类来组合对象树形的数据结构。但是例子2中部门的行为是完全一致的,因此例子2算是组合模式的一个变种,吸收了其设计思想,但是实现更简洁!!!
3.天然适合与访问者模式搭配起来使用
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
例1:实现文件目录和文件的树形结构
抽象类:Node
/**
* 将文件与目录统一看作是一类节点,做一个抽象类来定义这种节点,然后以其实现类来区分文件与目录,在实现类中分别定义各自的具体实现内容
*/
public abstract class Node {
protected String name;//名称
//构造器赋名
public Node(String name){
this.name = name;
}
//新增节点:文件节点无此方法,目录节点重写此方法
public void addNode(Node node) throws Exception{
throw new Exception("Invalid exception");
}
//显示节点:文件与目录均实现此方法
abstract void display();
}
文件实现类:Filter
/**
* 实现文件节点
*/
public class Filer extends Node {
//通过构造器为文件节点命名
public Filer(String name) {
super(name);
}
//显示文件节点
@Override
public void display() {
System.out.println(name);
}
}
目录实现类:Noder
import java.util.*;
/**
* 实现目录节点
*/
public class Noder extends Node {
List<Node> nodeList = new ArrayList<Node>();//内部节点列表(包括文件和下级目录)
//通过构造器为当前目录节点赋名
public Noder(String name) {
super(name);
}
//新增节点
public void addNode(Node node) throws Exception{
nodeList.add(node);
}
//递归循环显示下级节点
@Override
void display() {
System.out.println(name);
for(Node node:nodeList){
node.display();
}
}
}
测试类:Clienter
import java.io.File;
public class Clienter {
public static void createTree(Node node) throws Exception{
File file = new File(node.name);
File[] f = file.listFiles();
for(File fi : f){
if(fi.isFile()){
Filer filer = new Filer(fi.getAbsolutePath());
node.addNode(filer);
}
if(fi.isDirectory()){
Noder noder = new Noder(fi.getAbsolutePath());
node.addNode(noder);
createTree(noder);//使用递归生成树结构
}
}
}
public static void main(String[] args) {
Node noder = new Noder("E://ceshi");
try {
createTree(noder);
} catch (Exception e) {
e.printStackTrace();
}
noder.display();
}
}
执行输出结果:
E://ceshi
E:\ceshi\文件1.txt
E:\ceshi\目录1
E:\ceshi\目录1\文件2.txt
E:\ceshi\目录1\目录3
E:\ceshi\目录2
E:\ceshi\目录2\文件3.txt
例2:实现父子部门的树形结构
public class CompositePatternDemo {
public static void main(String[] args) {
Department leafDept1 = new Department("叶子部门1");
Department leafDept2 = new Department("叶子部门2");
Department leafDept3 = new Department("叶子部门3");
Department subDept1 = new Department("子部门1");
subDept1.getChildren().add(leafDept1);
subDept1.getChildren().add(leafDept2);
Department subDept2 = new Department("子部门2");
subDept2.getChildren().add(leafDept3);
Department parentDept = new Department("父部门");
parentDept.getChildren().add(subDept1);
parentDept.getChildren().add(subDept2);
parentDept.remove();
// 组合模式的第一要义,就是将树形结构的数据,用一个类,或者少数一两个类,就可以拼装成一棵树的形状
// 组合模式的第二要义,就是直接对一个父级的数据执行某个操作,这个操作会直接递归调用所有下层的子数据的相关操作
// 设计模式,重点,是思想,理解了思想,随便招式你怎么出,只要能将思想运用到实际业务场景中
// 避免写出屎一样的代码,你就成功了
// 如果你照搬设计模式去写,反而增加代码的复杂度
}
public static class Department {
private String name;
private List<Department> children = new ArrayList<Department>();
public Department(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Department> getChildren() {
return children;
}
public void setChildren(List<Department> children) {
this.children = children;
}
public void remove() {
if(children.size() > 0) {
for(Department child : children) {
child.remove();
}
}
System.out.println("删除部门【" + name + "】");
}
}
}
运行结果:
删除部门【叶子部门1】
删除部门【叶子部门2】
删除部门【子部门1】
删除部门【叶子部门3】
删除部门【子部门2】
删除部门【父部门】