组合模式
- 概述:将对象组合成树形结构以表示”部分-整体”的层次结构.使得用户对单个对象和组合对象的使用具有一致性.
- 应用场景:希望忽略单个对象和组合对象的区别,统一使用组合结构中的所有对象.也就是将单个对象和组合对象中的统一的地方封装起来.供外部调用.
- 组合模式中的角色
- 组合部件:它是一个抽象类,为要组合的对象提供统一的接口.
- 叶子:在组合中表示子节点对象,叶子节点已经是最底层不能再有子节点.
- 合成部件(分支):定义有子节点的行为,用来存储叶子或部件.实现Component抽象类的有关操作.
- 帮助理解:可以将组合模式想象成文件夹与文件的关系.文件夹里面可以继续创建文件夹或者文件,但是文件中不可以创建文件夹或者文件,在这里文件就是叶子节点,文件夹相当于分支.
- 实现组合模式的两种方式
- 透明方式(本例子使用的时透明方式)
- 在Component中声明所有用来管理子对象的方法(在本例子中就是Add,Rmove,Display等方法).这样它的子类都会具备其所有的方法.
- 好处:叶子节点和分支节点对外没有区别,具备完全一致的接口.
- 缺点:叶子根本就没有Add和Rmove的功能,所以实现没有意义.
- 安全方式
- 在Component中不声明Add和Rmove等这些不是共有的方法,在分支节点中再声明.
- 好处:去除无意义的实现
- 缺点:由于叶子节点和分支节点方法不统一,所以在使用时要对叶子节点和分支节点进行判定.这样为使用带来了不便
代码实现
示例: 因为组合模式很像树结构,所以一树结构为例.根据组合模式,表示一棵树
组合部件类
package Component;
/**
* Created by looper on 2017/8/17.
*/
public abstract class Component {
public String name;
public Component(String name){
this.name = name;
}
public abstract void Add(Component component);
public abstract void Rmove(Component component);
public abstract void Display();
}
叶子类
package Component;
/**
* Created by looper on 2017/8/17.
*/
public class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void Add(Component component) {
//叶子节点已经是最下面的了,不会再有子节点
System.out.println("\t叶子节点不能添加子节点");
}
@Override
public void Rmove(Component component) {
//叶子节点不存在子节点,所以更不能说删除了
System.out.println("\t叶子节点不能删除子节点");
}
@Override
public void Display() {
System.out.println("\t叶子节点: name = "+ name);
}
}
分支类(合成部件)
package Component;
import java.util.ArrayList;
import java.util.List;
/**
* Created by looper on 2017/8/17.
*/
public class Branch extends Component {
private List<Component> children = new ArrayList<>();
public Branch(String name) {
super(name);
}
@Override
public void Add(Component component) {
//为分支添加子分支或者子节点
children.add(component);
}
@Override
public void Rmove(Component component) {
//为分支删除子分支或子节点
children.remove(component);
}
@Override
public void Display() {
System.out.println("枝干: name = "+name);
for (Component component:children) {
component.Display();
}
}
}
测试类
package Component;
/**
* Created by looper on 2017/8/17.
*/
public class ComponentTest {
public static void main(String[] args) {
Component root = new Branch("根");
Component leafA = new Leaf("叶子节点A");
Component leafB = new Leaf("叶子节点B");
root.Add(leafA);
root.Add(leafB);
Component branchA = new Branch("分支A");
Component branchB = new Branch("分支B");
root.Add(branchA);
root.Add(branchB);
Component leafC = new Leaf("叶子节点C");
Component branchC = new Branch("分支C");
branchA.Add(leafC);
branchA.Add(branchC);
Component leafD = new Leaf("叶子节点D");
branchC.Add(leafD);
Component leafE = new Leaf("叶子节点E");
Component leafF = new Leaf("叶子节点F");
branchB.Add(leafE);
branchB.Add(leafF);
root.Display();
}
}
输出: