组合(Composite Pattern)模式的定义:有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。
Composite 比较容易理解,想到 Composite 就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时, Composite 将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。
组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点,树形结构图如下
Composite 好处:
1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。
package design.composite; //抽象构件 public interface Component { public void add(Component c); public void remove(Component c); public Component getChild(int i); public void operation(); public float calcSales(); }
package design.composite; import java.util.ArrayList; import java.util.List; public class Employee implements Component { // 名字 private String name; // 部门 private String dept; // 薪水 private int salary; // 下属list private List<Component> subordinates; //构造函数 public Employee(String name, String dept, int sal) { this.name = name; this.dept = dept; this.salary = sal; subordinates = new ArrayList<Component>(); } @Override public void add(Component c) { subordinates.add(c); } @Override public void remove(Component c) { subordinates.remove(c); } @Override public Component getChild(int i) { return subordinates.get(i); } @Override public void operation() { System.out.println(this.toString()); for (Object obj : subordinates) { ((Component) obj).operation(); } } @Override public float calcSales() { float s = this.salary; for (Object obj : subordinates) { s += ((Component) obj).calcSales(); } return s; } public String toString() { return ("Employee :[ Name : " + name + ", dept : " + dept + ", salary :" + salary + " ]"); } }
package design.composite; /** * 组合(Composite Pattern)模式的定义:有时又叫作整体-部分(Part-Whole)模式, * 它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系, * 使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。 * <p> * 在现实生活中,存在很多“部分-整体”的关系,例如,大学中的部门与学院、总公司中的部门与分公司、学习用品中的书与书包 * 在软件开发中也是这样,例如,文件系统中的文件与文件夹、窗体程序中的简单控件与容器控件等。 * 对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。 * <p> * 比如下列举例,CEO下面有2个负责人(分别属于销售和市场部门),每个负责人下面也有2个员工,形成下面树状结构 * 每个人都是一个节点,都可以有下级 * John(CEO) * Robert(Head Sales) Michel(Head Marketing) * Richard(Sales) Rob(Sales) Laura(Marketing) Bob(Marketing) */ public class CompositePattern { public static void main(String[] args) { Employee CEO = new Employee("John", "CEO", 30000); Employee headSales = new Employee("Robert", "Head Sales", 20000); Employee headMarketing = new Employee("Michel", "Head Marketing", 20000); Employee clerk1 = new Employee("Laura", "Marketing", 10000); Employee clerk2 = new Employee("Bob", "Marketing", 10000); Employee salesExecutive1 = new Employee("Richard", "Sales", 10000); Employee salesExecutive2 = new Employee("Rob", "Sales", 10000); CEO.add(headSales); CEO.add(headMarketing); headSales.add(salesExecutive1); headSales.add(salesExecutive2); headMarketing.add(clerk1); headMarketing.add(clerk2); // CEO的组织关系,根据根节点找到所有的子节点信息 CEO.operation(); // 计算CEO所有下属的薪水 System.out.println("sales sum:" + CEO.calcSales()); } }
运行结果:
Employee :[ Name : John, dept : CEO, salary :30000 ]
Employee :[ Name : Robert, dept : Head Sales, salary :20000 ]
Employee :[ Name : Richard, dept : Sales, salary :10000 ]
Employee :[ Name : Rob, dept : Sales, salary :10000 ]
Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ]
Employee :[ Name : Laura, dept : Marketing, salary :10000 ]
Employee :[ Name : Bob, dept : Marketing, salary :10000 ]
sales sum:110000.0
【例1】用组合模式实现当用户在商店购物后,显示其所选商品信息,并计算所选商品总价的功能。
说明:假如李先生到韶关“天街e角”生活用品店购物,用 1 个红色小袋子装了 2 包婺源特产(单价 7.9 元)、1 张婺源地图(单价 9.9 元);用 1 个白色小袋子装了 2 包韶关香藉(单价 68 元)和 3 包韶关红茶(单价 180 元);用 1 个中袋子装了前面的红色小袋子和 1 个景德镇瓷器(单价 380 元);用 1 个大袋子装了前面的中袋子、白色小袋子和 1 双李宁牌运动鞋(单价 198 元)。
最后“大袋子”中的内容有:{1 双李宁牌运动鞋(单价 198 元)、白色小袋子{2 包韶关香菇(单价 68 元)、3 包韶关红茶(单价 180 元)}、中袋子{1 个景德镇瓷器(单价 380 元)、红色小袋子{2 包婺源特产(单价 7.9 元)、1 张婺源地图(单价 9.9 元)}}},现在要求编程显示李先生放在大袋子中的所有商品信息并计算要支付的总价。
实现示意图:
参考文章:
组合模式 | 菜鸟教程
组合模式(详解版)