组合模式
概述
- 组合模式描述的是部分与整体的关系
- 内部结构分析根节点、分支节点、叶子节点
- 根节点为抽象接口,分支节点与叶子节点均需实现根节点接口;这样才可以实现客户端调用时对叶子节点与分支节点处理时的一致性
- 分支节点可包含若干个叶子节点
- 设计思想:在客户端调用时对叶子节点的处理方式与对分支节点的处理方式相同,即处理复杂对象的方式与处理简单对象的方式一样
- 组合部件(Component):它是一个抽象角色,为要组合的对象提供统一的接口
- 叶子(Leaf):在组合中表示子节点对象,叶子节点不能有子节点
- 合成部件(Composite):定义有枝节点的行为,用来存储部件,实现在Component接口中的有关操作,如增加(Add)和删除(Remove)
使用场景
- 当想表达对象的部分-整体的层次结构时;即一系列的按顺序的操作,每个操作对应一个叶子节点,组合起来就是分支节点,多个分支节点就是树形结构
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象时;即客户端在处理单个对象与组合对象时无差别
示例代码一
/**
* 一个抽象构件,声明一个接口用于访问和管理Component的子部件
*/
public abstract class Component {
private String name ;
public Component(String name){
this.name = name ;
}
/**
* 增加一个节点
* @param component
*/
public abstract void add(Component component);
/**
* 删除一个节点
* @param component
*/
public abstract void remove(Component component);
/**
* 显示层级结构
* @param level
*/
public abstract void display(int level);
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 叶子
public class Leaf extends Component{
public Leaf(String name) {
super(name);
}
@Override
public void add(Component component) {
System.out.println("Leaf can nod add component");
}
@Override
public void remove(Component component) {
System.out.println("Leaf can not remove component");
}
@Override
public void display(int level) {
StringBuilder stringBuilder = new StringBuilder("");
stringBuilder.append("-").append(level).append("-").append(super.getName());
System.out.println(stringBuilder.toString());
}
}
// 分支
import java.util.ArrayList;
import java.util.List;
public class Composite extends Component{
public Composite(String name) {
super(name);
}
private List<Component> chirldren = new ArrayList<Component>();
@Override
public void add(Component component) {
chirldren.add(component);
}
@Override
public void remove(Component component) {
chirldren.remove(component);
}
@Override
public void display(int level) {
StringBuilder stringBuilder = new StringBuilder("");
stringBuilder.append("-").append(level).append("-").append(super.getName());
System.out.println(stringBuilder.toString());
for (Component component: chirldren ) {
component.display(level+2);
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// 根
Component root = new Composite("Root");
// 根上的叶子
Component leaf1 = new Leaf("Leaf1 in Root");
Component leaf2 = new Leaf("Leaf2 in Root");
root.add(leaf1);
root.add(leaf2);
// 根上的分支
Component branchX = new Composite("Branch X in Root");
Component branchY = new Composite("Branch Y in Root");
root.add(branchX);
root.add(branchY);
// 分支的叶子
Component leaf3 = new Leaf("Leaf3 in Branch X");
Component leaf4 = new Leaf("Leaf4 in Branch X");
branchX.add(leaf3);
branchX.add(leaf4);
Component leaf5 = new Leaf("Leaf5 in Branch Y");
Component leaf6 = new Leaf("Leaf6 in Branch Y");
branchY.add(leaf5);
branchY.add(leaf6);
// 层级
root.display(1);
}
}
控制台输出结果
-1-Root
-3-Leaf1 in Root
-3-Leaf2 in Root
-3-Branch X in Root
-5-Leaf3 in Branch X
-5-Leaf4 in Branch X
-3-Branch Y in Root
-5-Leaf5 in Branch Y
-5-Leaf6 in Branch Y
项目应用一
// 客户端
public abstract class AbstractRequestProcessorModel<Request, Result> {
// 合成部件:由一系列的叶子节点组成,LinkedHashSet 叶子节点按注入顺序依次执行
protected LinkedHashSet<Component<Request>> components;
// 对单一对象与组合对象的一致性处理
protected void executeComponent(Request request) {
for (Component<Request> component : components) {
component.execute(request);
}
}
}
// 组合部件,对外提供统一的抽象接口
public abstract class Component<Request> {
public void execute(Request request) {
doBusiness(request);
}
// 由叶子节点继承并实现具体的业务逻辑
protected abstract void doBusiness(Request request);
}
// 叶子节点:继承组合部件并实现具体的业务逻辑
public class XInfoComponent extends BaseComponent<DetailRequest> {
@Override
protected void doBusiness(DetailRequest request) {
// TODO
}
}
// 其他叶子节点
// 组合部件添加叶子节点:由Spring配置文件注入依赖
// 1. web.xml : 加载 Spring 配置文件
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-xxx.xml</param-value>
</context-param>
// 2. application-xxx.xml:加载 Spring 配置文件:component.xml
<import resource="classpath*:component.xml"/>
// 3. component.xml 为客户端的子类bean注入LinkedHashSet属性
<bean id="xxxListProcessor" class="com.xxx.xxxListProcessor">
<property name="components">
<set>
<ref bean="xInfoComponent"/>
......
</set>
</property>
</bean>
- 客户端采用模板设计模式,模板类中包含组合模式中合成部件;子类实现客户端模板类,可直接引用父类中的全局变量
- 模板设计模式:定义公共的组合部件,各个叶子节点均继承组合部件并实现自己的业务逻辑
- 通过Spring加载注入到客户端的子类中
- 项目初始化时加载Sevlet容器,就将相应的叶子节点配置到对应客户端的子类的全局变量(合成部件)中
- 项目运行时,遍历合成部件,依次执行各个叶子节点的具体业务逻辑
- 定义公共的参数类,参数类可依次添加每个步骤执行的结果,并为下一个步骤的执行带上必须要的参数条件;即前一个叶子节点的执行结果可通过参数类,带到下一个叶子结果作为参数条件