定义:
- 将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
/*
* 创建抽象构建
* */
public abstract class Component {
// 个体和整体共有的方法
public void doSomething() {
}
}
/*
* 创建树枝组件
* */
public class Composite extends Component {
// 构架容器
private ArrayList<Component> componentArrayList = new ArrayList<>();
public void add(Component component) {
this.componentArrayList.add(component);
}
public void remove(Component component) {
this.componentArrayList.remove(component);
}
public ArrayList<Component> getChildren() {
return this.componentArrayList;
}
}
/*
* 创建最小的组件
* */
public class Leaf extends Component {
@Override
public void doSomething() {
// TODO Auto-generated method stub
super.doSomething();
}
}
public class Client {
public static void main(String[] args) {
// 创建根节点
Composite root = new Composite();
// 创建树枝节点
Composite branch = new Composite();
// 创建树叶
Leaf leaf = new Leaf();// 违反依赖倒转原则
root.add(branch);
branch.add(leaf);
}
// 递归遍历节点
public static void display(Composite root) {
for (Component c : root.getChildren()) {
if (c instanceof Leaf) {
c.doSomething();
} else {
display((Composite) c);
}
}
}
}
优点:
- 高层模块的调用简单,所有的节点都是Component,局部和整体对调用者来说没有任何区别,高层模块不关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。
- 节点自由增加
缺点:
- 定义时候直接使用的是实现类,这在面向接口编程上是很不恰当的,与依赖倒置原则冲突。
组合模式的拓展:
- 透明的组合模式(透明模式是把用来组合使用的方法放到抽象类中,通过判断getChildren的返回值确认是叶子节点还是书直接点,如果处理不当,这个会在运行期间出现问题):
public abstract class Component {
public void doSomething() {
}
public abstract void add(Component component);
public abstract void remove(Component component);
public abstract ArrayList<Component> getChildren();
}
public class Leaf extends Component {
@Deprecated
public void add(Component component) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
@Deprecated
public void remove(Component component) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
@Deprecated
public ArrayList<Component> getChildren() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
}
public class Client {
public static void main(String[] args) {
}
public static void display(Component root) {
for (Component c : root.getChildren()) {
if (c instanceof Leaf) {
c.doSomething();
} else {
/*
* 不再使用强制类型转换,遵循依赖倒转原则
*/
display(c);
}
}
}
}
- 组合模式的遍历(可以通过在节点中添加对应的父节点对象信息,使得从子节点遍历的时候可以查询到相关的父节点信息)