Java 设计模式08——组合模式

模式定义

合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

从上面的定义可以提取到以下关键词:部分与整体、树形结构。

模式示例

利用组合模式来打印出一个公司员工的树形结构。定义一个员工类Employee,该类被用作组合的模型类,所有其他角色员工都继承该类。角色包括CEO、销售经理、销售、市场经理、市场专员。CEO下有销售经理、市场专员;销售经理下有销售;市场经理下面有市场专员。

定义Employee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Employee {
public String name;
public String dept;
public List<Employee> subEmployees;

public Employee(String name, String dept) {
this.name = name;
this.dept = dept;
subEmployees = new ArrayList<>();
}

public void addEmployee(Employee employee) {
subEmployees.add(employee);
}

public void removeEmployee(Employee employee) {
subEmployees.remove(employee);
}

@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", dept='" + dept + '\'' +
'}';
}
}

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Client {
public static void main(String[] args) {
Employee ceo = new Employee("Randy", "CEO");

Employee saleMgr = new Employee("Randy1", "Sales");

Employee marketMgr = new Employee("Randy2", "Markets");

Employee saleOne = new Employee("Randy3", "Sales");
Employee saleTwo = new Employee("Randy4", "Sales");

Employee marketOne = new Employee("Randy5", "Market");
Employee marketTwo = new Employee("Randy6", "Market");

ceo.addEmployee(saleMgr);
ceo.addEmployee(marketMgr);

saleMgr.addEmployee(saleOne);
saleMgr.addEmployee(saleTwo);

marketMgr.addEmployee(marketOne);
marketMgr.addEmployee(marketTwo);

System.out.println(ceo);
for (Employee employee : ceo.subEmployees) {
System.out.println(" " + employee);
for (Employee employee1 : employee.subEmployees) {
System.out.println(" " +employee1);
}
}
}
}
// 输出结果
Employee{name='Randy', dept='CEO'}
Employee{name='Randy1', dept='Sales'}
Employee{name='Randy3', dept='Sales'}
Employee{name='Randy4', dept='Sales'}
Employee{name='Randy2', dept='Markets'}
Employee{name='Randy5', dept='Market'}
Employee{name='Randy6', dept='Market'}

只要定义一个类,然后通过在Client中进行组合就可以实现组织架构的打印了,很简单。

模式总结

优缺点

  • 优点
    • 结构简单,同时添加节点容易,比如要新增一个开发部门,只需要创建一个开发经理以及几个普通开发者即可
    • 操作简单,不论什么角色,操作的方法都一样,因为都是Employee对象;
    • 模糊了简单元素与复杂元素的概念,所有元素都可以向处理普通元素一样处理。
  • 缺点
    • 上面的示例中,所有的角色都是用一个类表示的,而不是通过接口实现来区分的,违背了依赖倒置原则

使用场景

  • 部分与整体的场景,如组织架构、文件与文件树,Android的View树结构等。
  • 希望忽略组合对象和单个对象不同时。