组合模式有时又称部分一整体模式,它将对象组织到树形结构中,可以用来描述整体与部分的关系。组合模式可以使
客户端将单纯与复合元素同等看待。
关键技术:根据所实现接口的不同,组合模式可分为两种,透明模式和安全模式。组合模式可以不提供父对象的管理方法
,但它必须在合适的地方提供子对象的管理方法(例Add()方法、Remove()方法)。
透明模式:在组合结构中声明所有用来管理子类对象的方法,包括Add()方法和Remove()方法。这样做的好处是所有的构件类
都有相同的接口。
安全模式:在组合结构类中声明所有用来管理子类对象的方法。
1.定义一个抽象类AComponent,并声明相关接口。
package org.java.Test;
/**
* @author Lee
* @param:name
* @param:AComponent
* @date:2018.11.28 23.14
*
* */
public abstract class AComponent {
protected String name;
public AComponent(String name) {
System.out.println(name);
}
abstract public void Add(AComponent c); //添加节点
abstract public void Remove(AComponent c);//移除节点
abstract public void Display(int AComponent);//输出节点结构
}
2.定义一个Composite,继承抽象类ACompnent。
package org.java.Test;
import java.util.ArrayList;
import java.util.Iterator;
/**
* @author Lee
* 功能:实现组合模式的核心功能
* @date:2018.11.28 23:19
*
* */
public class Composite extends AComponent{
static AComponent component;
private ArrayList children=new ArrayList();
public Composite(String name) {
super(name);
}
@Override
public void Add(AComponent component) {
this.component=component;
children.add(component);
}
@Override
public void Remove(AComponent component) {
children.remove(component);
}
@Override
public void Display(int i) {
Iterator iterator=children.iterator();
AComponent ac=null;
ac=(AComponent) iterator.next();
while(iterator.hasNext()&&iterator.next().equals(null)){
System.out.println(ac.name);
}
}
}
3.定义一个类Leaf,用来向树状结构中添加子项。
package org.java.Test;
/**
* @author Lee
* 功能:用来向树状结构中添加子项
* @date:2018.11.28 23:30
* */
public class Leaf extends AComponent{
public Leaf(String name) {
super(name);
}
@Override
public void Add(AComponent c) {
System.out.println("不能添加子项!");
}
@Override
public void Remove(AComponent c) {
System.out.println("不能移出子项!");
}
@Override
public void Display(int AComponent) {
System.out.println(new String()+name);
}
}
4.测试类
package org.java.Test;
/**
* @author Lee
* 功能:测试利用透明模式的组合模式生成一个树状结构
* @date:2018.11.28 23:32
* */
public class Client {
public static void main(String[] args) {
//建立一个树状结构
Composite root=new Composite("根目录"); //创建一个根元素(根元素也是复合元素)
root.Add(new Leaf("....子项A"));
root.Add(new Leaf("....子项B"));
Composite comp=new Composite("组合X"); //创建一个复合元素
comp.Add(new Leaf("....子项XA"));
comp.Add(new Leaf("....子项XB"));
root.Add(comp); //将复合元素添加到根元素
root.Add(new Leaf("....子项C")); //将单纯元素添加到根元素
//添加和移出一个子项
Leaf l=new Leaf("....子项D");
root.Add(l);
root.Remove(l);
//通过递归输出子节点
root.Display(1);
}
}
秘笈心法:
1.给出明显的父对象的引用。在子对象中给出父对象的引用,这样可以很容易地遍历所有父对象。可以方便的应用责任链模式。
2.在特殊情况下,系统需要多次遍历一个树枝结构的子构件,此时应该考虑把遍历子构件的结果暂时存储在父构件中作为缓存。
3.客户端尽量不要直接调用树叶类中的方法,而是借助父类的多态性完成调用,这样可以增加代码的复用性。