Design Patterns教程-组合模式
组合模式表示 “允许客户端以统一的方式处理对象,这些对象可能表示对象的层次结构”。
组合设计模式的优点
- 它定义了包含原始对象和复杂对象的类层次结构。
- 它使添加新类型的组件更加容易。
- 它提供了具有可管理的类或接口的结构灵活性。
组合模式的使用
适用于以下情况:
- 当你想表示对象的完整或部分层次结构时。
- 当需要动态添加职责到个别对象而不影响其他对象时。对象的职责可能会随时间而变化。
组合模式的 UML
组合模式的元素:
我们来看一下组合模式的4个元素。
1) 组件(Component)
- 声明组合中对象的接口。
- 为所有类的通用接口实现默认行为(如果适用)。
- 声明访问和管理子组件的接口。
2) 叶子(Leaf)
- 表示组合中的叶对象。叶子没有子对象。
- 为组合中的原始对象定义行为。
3) 组合(Composite)
- 定义有子对象的组件的行为。
- 存储子组件。
- 在组件接口中实现与子相关的操作。
4) 客户端(Client)
- 通过组件接口操作组合中的对象。
注意:上面通用 UML 的工作流程如下。
客户端使用组件类接口与组合结构中的对象进行交互。如果接收者是叶子节点,则请求将直接处理。如果接收者是组合节点,则通常会将请求转发给其子节点以执行附加操作。
组合模式示例
我们可以通过下面给出的 UML 图轻松理解组合设计模式的示例:
实现上述 UML:
步骤 1
创建一个 Employee 接口,将其视为 组件(Component)。
// 这是 Employee 接口,即组件。
public interface Employee {
public int getId();
public String getName();
public double getSalary();
public void print();
public void add(Employee employee);
public void remove(Employee employee);
public Employee getChild(int i);
}
// 组件接口结束。
步骤 2
创建一个 BankManager 类,将其视为 组合(Composite) 并实现 Employee 接口。
文件:BankManager.java
// 这是 BankManager 类,即组合。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class BankManager implements Employee {
private int id;
private String name;
private double salary;
public BankManager(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
List<Employee> employees = new ArrayList<Employee>();
@Override
public void add(Employee employee) {
employees.add(employee);
}
@Override
public Employee getChild(int i) {
return employees.get(i);
}
@Override
public void remove(Employee employee) {
employees.remove(employee);
}
@Override
public int getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void print() {
System.out.println("==========================");
System.out.println("Id = " + getId());
System.out.println("Name = " + getName());
System.out.println("Salary = " + getSalary());
System.out.println("==========================");
Iterator<Employee> it = employees.iterator();
while (it.hasNext()) {
Employee employee = it.next();
employee.print();
}
}
}
// BankManager 类结束。
步骤 3
创建一个 Cashier 类,将其视为 叶子(Leaf) 并实现 Employee 接口。
文件:Cashier.java
public class Cashier implements Employee {
/*
在此类中,有许多方法不适用于 Cashier,因为
它是叶节点。
*/
private int id;
private String name;
private double salary;
public Cashier(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
@Override
public void add(Employee employee) {
// 这是叶节点,因此此方法不适用于此类。
}
@Override
public Employee getChild(int i) {
// 这是叶节点,因此此方法不适用于此类。
return null;
}
@Override
public int getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void print() {
System.out.println("==========================");
System.out.println("Id = " + getId());
System.out.println("Name = " + getName());
System.out.println("Salary = " + getSalary());
System.out.println("==========================");
}
@Override
public void remove(Employee employee) {
// 这是叶节点,因此此方法不适用于此类。
}
}
步骤 4
创建一个 Accountant 类,也将其视为 叶子(Leaf) 并实现 Employee 接口。
文件:Accountant.java
public class Accountant implements Employee {
/*
在此类中,有许多方法不适用于 Accountant,因为
它是叶节点。
*/
private int id;
private String name;
private double salary;
public Accountant(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
@Override
public void add(Employee employee) {
// 这是叶节点,因此此方法不适用于此类。
}
@Override
public Employee getChild(int i) {
// 这是叶节点,因此此方法不适用于此类。
return null;
}
@Override
public int getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void print() {
System.out.println("=========================");
System.out.println("Id = " + getId());
System.out.println("Name = " + getName());
System.out.println("Salary = " + getSalary());
System.out.println("=========================");
}
@Override
public void remove(Employee employee) {
// 这是叶节点,因此此方法不适用于此类。
}
}
步骤 5
创建一个 CompositePatternDemo 类,将其视为 客户端(Client) 并使用 Employee 接口。
文件:CompositePatternDemo.java
public class CompositePatternDemo {
public static void main(String args[]) {
Employee emp1 = new Cashier(101, "Sohan Kumar", 20000.0);
Employee emp2 = new Cashier(102, "Mohan Kumar", 25000.0);
Employee emp3 = new Accountant(103, "Seema Mahiwal", 30000.0);
Employee manager1 = new BankManager(100, "Ashwani Rajput", 100000.0);
manager1.add(emp1);
manager1.add(emp2);
manager1.add(emp3);
manager1.print();
}
}
输出
==========================
Id = 100
Name = Ashwani Rajput
Salary = 100000.0
==========================
==========================
Id = 101
Name = Sohan Kumar
Salary = 20000.0
==========================
==========================
Id = 102
Name = Mohan Kumar
Salary = 25000.0
==========================
=========================
Id = 103
Name = Seema Mahiwal
Salary = 30000.0
=========================