文章目录
1.动机
软件在某些情况下,客户代码过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等弊端。
2.定义
组合模式,将对象组合成树形结构以表示 ‘ 部分-整体 ’ 的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
3.使用场景
出现树形结构的地方:如文件管理系统、办公管理系统(如图)。
4.UML图
5.透明方式和安全方式
两者各有好处,视情况而定
5.1透明方式
在Component中 声明所有管理子对象的方法,实现Component接口的所有子类都具各Add和Remove以及Display等方法。
5.1.1 优点
叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口,客户端可以同等的对待所有的对象。
5.1.2 缺点:
不够安全,因为树叶类对象和合成类对象在本质.上是有区别的。树叶类对象不可能有下一个层次的对象,因此add()、remove()以及Display()方法没有意义。
5.2安全方式
在Component中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在合成类Composite (不是Component类)声明所有用来管理子类对象的方法。
5.2.1 优点
这样的做法是安全的做法,树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。
5.2.2 缺点
不够透明,树叶类和合成类将具有不同的接口,客户端的调用雪要做相应的判断,带来了不便。
6.代码模板(使用透明方式)
Component
//节点抽象类
abstract class Component {
protected String name;
public Component(String name) {
super();
this.name = name;
}
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
Leaf
//叶子节点
class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void Add(Component c) {
System.out.println("can't add to a leaf!");
}
@Override
public void Remove(Component c) {
System.out.println("can't remove from a leaf");
}
@Override
public void Display(int depth) {
for(int i = 1;i<depth;i++)
System.out.print(" ");
System.out.println("--" + depth + name); //显示节点内容
}
}
Composite
//分支节点
class Composite extends Component {
private List<Component> children = new ArrayList<Component>(); //用list存放下级节点(叶子节点或分支节点)
public Composite(String name) {
super(name);
}
@Override
public void Add(Component c) {
this.children.add(c);
}
@Override
public void Remove(Component c) {
this.children.remove(c);
}
@Override
public void Display(int depth) {
for(int i = 1;i<depth;i++)
System.out.print(" ");
System.out.println("--" + depth + name); //显示节点内容
for (Component component : children) { //遍历下级节点
component.Display(depth + 1);
}
}
}
Client
//客户端代码
public class Main {
public static void main(String[] args) {
//给root根节点添加叶子
Composite root = new Composite("root");
root.Add(new Leaf("Leaf RA"));
root.Add(new Leaf("Leaf RB"));
//给分支节点comp添加叶子
Composite comp = new Composite("comp");
comp.Add(new Leaf("Leaf CA"));
comp.Add(new Leaf("Leaf CB"));
//将comp 加入到root下
root.Add(comp);
//给分支节点comp2添加叶子,并加到comp下
Composite comp2 = new Composite("comp2");
comp2.Add(new Leaf("Leaf C2A"));
comp2.Add(new Leaf("Leaf C2B"));
comp.Add(comp2);
Leaf leaf_c = new Leaf("leaf_c");
root.Add(leaf_c);
//打印信息
root.Display(1);
}
}