参考
组合模式
组合模式
类型:结构型模式
将对象组合成树形结构来表示“部分-整体”的层次结构,使得客户能以一致的方式处理个别对象和组合对象。
如何解决:叶子和组合节点实现统一接口,叶子和组合节点分别重写接口的方法,使得调用方法一致但产生不同结果。
关键代码:组合节点内部组合该接口,并且含有内部属性 List,里面放 Component。
角色
- Component 抽象组件:为组合中所有对象提供一个接口,不管是叶子对象还是组合对象。
- Composite 组合节点对象:实现了Component的所有操作,并且持有子节点对象。
- Leaf 叶节点对象:叶节点对象没有任何子节点,实现了Component中的某些操作。
UML
包结构
component(基类)
package 组合模式.component;
import java.util.List;
public abstract class Node {
protected String name;
public Node(String name) {
this.name = name;
}
public abstract void doOperation();
public void add(Node c) {
System.out.println("叶子结点不能添加子结点");
}
public void remove(Node c) {
System.out.println("叶子结点没有子结点");
}
public Node getChild(int i) {
System.out.println("叶子结点没有子结点");
return null;
}
public List<Node> getChildren() {
System.out.println("叶子结点没有子结点");
return null;
}
}
两个子类
leaf
package 组合模式.leaf;
import 组合模式.component.Node;
public class Leaf extends Node {
public Leaf(String name) {
super(name);
}
@Override
public void doOperation() {
System.out.println("-----叶子节点:"+name+"的操作-----");
}
}
composite
package 组合模式.composite;
import 组合模式.component.Node;
import java.util.ArrayList;
import java.util.List;
public class NotLeaf extends Node {
private List<Node> nodes = new ArrayList<>();
public NotLeaf(String name) {
super(name);
}
@Override
public void doOperation() {
System.out.println("-----非叶结点:"+name+"的操作-----");
//进行所有子节点的操作
for (Node node : nodes) {
node.doOperation();
}
}
@Override
public void add(Node c) {
nodes.add(c);
}
@Override
public void remove(Node c) {
nodes.remove(c);
}
@Override
public Node getChild(int i) {
return nodes.get(i);
}
@Override
public List<Node> getChildren() {
return nodes;
}
}
client(就随便调用方法了,这个模式的树结构在输出语句上看起来挺麻烦)
package 组合模式.client;
import 组合模式.component.Node;
import 组合模式.composite.NotLeaf;
import 组合模式.leaf.Leaf;
public class Client {
public static void main(String[] args) {
Node node1 = new NotLeaf("根结点");
Node node2 = new Leaf("第一个叶子结点");
Node node3 = new NotLeaf("第一个非叶结点");
node1.add(node2);
node1.add(node3);
node1.doOperation();
System.out.print('\n');
Node node4 = new Leaf("第二个叶子结点");
Node node5 = new NotLeaf("第二个非叶结点");
node2.add(node4);
node3.add(node5);
node5.add(node4);
node5.doOperation();
System.out.print('\n');
node1.doOperation();
System.out.print('\n');
node1.remove(node3);
node1.doOperation();
System.out.print('\n');
}
}
效果
-----非叶结点:根结点的操作-----
-----叶子节点:第一个叶子结点的操作-----
-----非叶结点:第一个非叶结点的操作-----
叶子结点不能添加子结点
-----非叶结点:第二个非叶结点的操作-----
-----叶子节点:第二个叶子结点的操作-----
-----非叶结点:根结点的操作-----
-----叶子节点:第一个叶子结点的操作-----
-----非叶结点:第一个非叶结点的操作-----
-----非叶结点:第二个非叶结点的操作-----
-----叶子节点:第二个叶子结点的操作-----
-----非叶结点:根结点的操作-----
-----叶子节点:第一个叶子结点的操作-----
Process finished with exit code 0
优点
-
组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
-
更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
缺点
-
设计较复杂,客户端需要花更多时间理清类之间的层次关系;
-
不容易限制容器中的构件;
-
不容易用继承的方法来增加构件的新功能;