Composite模式将对象组合成树形结构以表示“部分-整体”的层次结构。它使得用户对单个对象和组合对象的使用具有一致性。
类图:
案例:
一个类使用两个几乎一样的方法,唯一不同的区别就是用一个处理单一对象,一个处理对象的集合。Composite模式可以处理这种一/多之分。
下面的代码是统计每个员工的成本和每个部门的成本(假设成本是员工的工资),通过重构技术实现Composite模式:
Step 1: 原始的类代码
public class Employee {
private int employId;
private String name;
private int salary;
public Employee(int employId, String name, int salary) {
this.employId = employId;
this.name = name;
this.salary = salary;
}
public int payment() {
return salary;
}
public String getName() {
return name;
}
public int getEmployId() {
return employId;
}
}
public class Department {
private String name;
private Set<Employee> employees = new HashSet<Employee>();
public Department(String name) {
this.name = name;
}
public int totalPayment() {
int results = 0;
Iterator<Employee> iter = employees.iterator();
while(iter.hasNext()) {
Employee ele = iter.next();
results += ele.payment();
}
return results;
}
public void add(Employee employee) {
employees.add(employee);
}
public void remove(Employee employee) {
employees.remove(employee);
}
}
Step 2: 将Department的totalPayment方法重命名为payment (Rename Method), 然后抽取父类(Extract Superclass),上移方法(Pull up Method).
public abstract class Party {
private String name;
public Party(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract int payment();
public void add(Party party) {
//hook method
}
public void remove(Party party) {
//hook method
}
}
public class Employee extends Party {
private int employId;
private int salary;
public Employee(int employId, String name, int salary) {
super(name);
this.employId = employId;
this.salary = salary;
}
public int payment() {
return salary;
}
public int getEmployId() {
return employId;
}
}
public class Department extends Party {
private Set<Party> parties = new HashSet<Party>();
public Department(String name) {
super(name);
}
public int payment() {
int results = 0;
Iterator<Party> iter = parties.iterator();
while(iter.hasNext()) {
Party ele = iter.next();
results += ele.payment();
}
return results;
}
public void add(Party party) {
parties.add(party);
}
public void remove(Party party) {
parties.remove(party);
}
}
客户代码
public class PartyTest {
@Test
public void testPayment() {
Party emp1 = new Employee(1, "Allen",10000);
Party emp2 = new Employee(2, "Sunny", 20000);
Party sales = new Department("Sales");
sales.add(emp1);
sales.add(emp2);
assertEquals("payment of sales is 30000", 30000, sales.payment());
Party emp3 = new Employee(3, "Sam", 30000);
Party emp4 = new Employee(4, "Grace", 40000);
Party development = new Department("Development");
development.add(emp3);
development.add(emp4);
assertEquals("payment of development is 70000", 70000, development.payment());
Party sz = new Department("Shenzhen");
sz.add(sales);
sz.add(new Employee(1, "Erik", 40000));
sz.add(development);
assertEquals("payment of Shenzhen is 140000", 140000, sz.payment());
}
}