定义:
组合多个对象形成树形结构以表示具有部分-整 体关系的层次结构。组合模式让客户端对单个对 象和组合对象的使用具有一致性。(组合模式屏蔽了单个对象与容器对象在使用时候的差异,为客户端提供统一的操作接口)。
结构图:
例子:
/*
* 公司类:充当抽象构件类
*/
public abstract class Company {
protected String name;
public Company(String name) {
this.name = name;
}
public abstract void Add(Company c);
public abstract void Remove(Company c);
public abstract void Display(int depth);
public abstract void LineOfDuty();
}
/*
* 具体公司:充当容器构件类
*/
public class ConcreteCompany extends Company {
private List<Company> children = new ArrayList<Company>();
public ConcreteCompany(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void Add(Company c) {
children.add(c);
}
@Override
public void Remove(Company c) {
children.remove(c);
}
@Override
public void Display(int depth) {
System.out.println("-" + name);
for (Company c : children) {
for (int i = 0; i < depth; i++) {
System.out.print("--");
}
c.Display(depth + 2);
}
}
@Override
public void LineOfDuty() {
for (Company c : children) {
c.LineOfDuty();
}
}
}
/*
* 公司具体部门1:充当叶子节点
*/
public class HRDepartment extends Company{
public HRDepartment(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void Add(Company c) {
// TODO Auto-generated method stub
}
@Override
public void Remove(Company c) {
// TODO Auto-generated method stub
}
@Override
public void Display(int depth) {
System.out.println("-" + name);
}
@Override
public void LineOfDuty() {
System.out.println(name + " staffs' trainning and managing");
}
}
/*
* 公司具体部门2:充当叶子节点
*/
public class FinanceDepartment extends Company {
......
}
public class CompositeMain {
public static void main(String[] args) {
ConcreteCompany root = new ConcreteCompany("Beijing");
root.Add(new HRDepartment("Beijing HR"));
root.Add(new FinanceDepartment("Beijing Finance"));
ConcreteCompany comp = new ConcreteCompany("Shanghai");
comp.Add(new HRDepartment("Shanghai HR"));
comp.Add(new FinanceDepartment("Shanghai Finance"));
root.Add(comp);
ConcreteCompany comp1 = new ConcreteCompany("Hangzhou");
comp1.Add(new HRDepartment("Hangzhou HR"));
comp1.Add(new FinanceDepartment("Hangzhou Finance"));
comp.Add(comp1);
ConcreteCompany comp2 = new ConcreteCompany("Nanjing");
comp2.Add(new HRDepartment("Nanjing HR"));
comp2.Add(new FinanceDepartment("Nanjing Finance"));
comp.Add(comp2);
System.out.println("\nConstruct-Map");
root.Display(1);
System.out.println("\nDuty");
root.LineOfDuty();
}
}
组合模式优点:
其实它的目的就是让客户可以一致地使用组合结构和单个对象。而组合模式定义了包含基本对象和组合对象的类层次结构,基本对象可以被组合成更复制的组合对象,这个组合对象还可以被组合,一直递归下去,在代码中任何用到基本对象的地方也都可以用组合对象。用户不用去关心处理的是一个基本对象还是组合对象,也就是不用为定义组合而写一些选择判断语句了。
透明组合模式与安全组合模式:
透明组合模式是在Component中声明了所有用于管理子类的 方法,包括add()、remove(),以及getChild()等 。这样实现Component接口的所有子类都具备了add()、remove(),以及getChild()等方法。好处是叶节点和枝节点有完全一样的行为接口,没有什么区别。但Leaf类本身不具有add()、remove(),以及getChild()等方法的功能,造成了多余的实现。
安全组合模式是在Component中不去声明add()、remove(),以及getChild()等 方法。那么子类Leaf就不需要去实现它。而是在Composite声明所有用于管理子类的方法。但这样的问题是叶节点和枝节点将不具有相同的接口。客户端在调用时需要做相应的判断。
所谓鱼与熊掌不可兼得,只能权衡选择~