设计模式-组合模式
什么是组合模式?
组合模式是一种结构型设计模式,它允许你将对象组合成树形结构来表示"部分-整体"的层次关系。组合模式使得客户端对单个对象和组合对象的使用具有一致性。
组合模式包含以下角色:
- 组件(Component):声明组合中对象的接口,适当情况下实现所有类共有接口的默认行为
- 叶子(Leaf):表示叶子节点对象,没有子节点
- 复合节点(Composite):定义有子部件的部件行为,存储子部件,并在Component接口中实现与子部件有关的操作
- 客户端(Client):通过Component接口操作组合部件的对象
组合模式的优缺点
优点:
- 统一处理:客户端可以一致地使用组合结构和单个对象
- 灵活性:容易增加新的组件类型,符合开闭原则
- 简化客户端代码:客户端不需要区分叶子节点和组合节点
- 层次结构清晰:能够清晰地表示对象之间的层次关系
缺点:
- 设计复杂:系统中存在大量小对象,系统更复杂
- 难以限制容器中的构件:很难限制组合中的构件类型
- 不易控制构件类型:不容易用继承的方法来增加新的行为
什么场景下使组合模式
- 表示对象的部分-整体层次结构
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
- 需要遍历组织机构树、文件系统、菜单系统等树形结构
- 需要动态地组合对象,形成复杂的层次结构
代码举例
下面是以组织架构为例子
// 组件接口 - 员工组件
abstract class EmployeeComponent {
protected String name;
protected String position;
public EmployeeComponent(String name, String position) {
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public String getPosition() {
return position;
}
// 抽象方法
public abstract void display(int depth);
public abstract double getSalary();
public abstract int getEmployeeCount();
public abstract double getTotalSalary();
// 默认实现
public boolean add(EmployeeComponent employee) {
throw new UnsupportedOperationException("不支持添加员工");
}
public boolean remove(EmployeeComponent employee) {
throw new UnsupportedOperationException("不支持删除员工");
}
public List<EmployeeComponent> getSubordinates() {
throw new UnsupportedOperationException("不支持获取下属");
}
}
// 叶子节点 - 普通员工
class Employee extends EmployeeComponent {
private double salary;
public Employee(String name, String position, double salary) {
super(name, position);
this.salary = salary;
}
@Override
public void display(int depth) {
String indent = " ".repeat(depth);
System.out.println(indent + "👤 " + name + " - " + position + " (薪资: ¥" + salary + ")");
}
@Override
public double getSalary() {
return salary;
}
@Override
public int getEmployeeCount() {
return 1;
}
@Override
public double getTotalSalary() {
return salary;
}
}
// 复合节点 - 管理者
class Manager extends EmployeeComponent {
private double baseSalary;
private List<EmployeeComponent> subordinates = new ArrayList<>();
public Manager(String name, String position, double baseSalary) {
super(name, position);
this.baseSalary = baseSalary;
}
@Override
public boolean add(EmployeeComponent employee) {
return subordinates.add(employee);
}
@Override
public boolean remove(EmployeeComponent employee) {
return subordinates.remove(employee);
}
@Override
public List<EmployeeComponent> getSubordinates() {
return new ArrayList<>(subordinates);
}
@Override
public void display(int depth) {
String indent = " ".repeat(depth);
System.out.println(indent + "💼 " + name + " - " + position +
" (基本薪资: ¥" + baseSalary + ", 下属: " + subordinates.size() + "人)");
for (EmployeeComponent subordinate : subordinates) {
subordinate.display(depth + 1);
}
}
@Override
public double getSalary() {
return baseSalary;
}
@Override
public int getEmployeeCount() {
int count = 1; // 包括自己
for (EmployeeComponent subordinate : subordinates) {
count += subordinate.getEmployeeCount();
}
return count;
}
@Override
public double getTotalSalary() {
double total = baseSalary;
for (EmployeeComponent subordinate : subordinates) {
total += subordinate.getTotalSalary();
}
return total;
}
// 获取特定职位的员工
public List<EmployeeComponent> getEmployeesByPosition(String position) {
List<EmployeeComponent> result = new ArrayList<>();
collectEmployeesByPosition(position, result);
return result;
}
private void collectEmployeesByPosition(String targetPosition, List<EmployeeComponent> result) {
if (this.position.equals(targetPosition)) {
result.add(this);
}
for (EmployeeComponent subordinate : subordinates) {
if (subordinate.getPosition().equals(targetPosition)) {
result.add(subordinate);
}
if (subordinate instanceof Manager) {
((Manager) subordinate).collectEmployeesByPosition(targetPosition, result);
}
}
}
}
// 客户端使用示例
public class OrganizationDemo {
public static void main(String[] args) {
// 创建CEO
Manager ceo = new Manager("张三", "CEO", 100000);
// 创建部门经理
Manager cto = new Manager("李四", "CTO", 80000);
Manager cfo = new Manager("王五", "CFO", 75000);
Manager hrManager = new Manager("赵六", "HR经理", 60000);
// 创建技术团队
Manager techManager = new Manager("钱七", "技术经理", 50000);
Employee developer1 = new Employee("孙八", "高级开发工程师", 35000);
Employee developer2 = new Employee("周九", "中级开发工程师", 25000);
Employee developer3 = new Employee("吴十", "初级开发工程师", 18000);
Employee qaEngineer = new Employee("郑一", "测试工程师", 22000);
// 创建财务团队
Employee accountant1 = new Employee("王二", "高级会计师", 28000);
Employee accountant2 = new Employee("冯三", "会计师", 22000);
// 创建HR团队
Employee recruiter = new Employee("陈四", "招聘专员", 18000);
Employee trainer = new Employee("褚五", "培训专员", 16000);
// 构建组织架构
// CEO下属
ceo.add(cto);
ceo.add(cfo);
ceo.add(hrManager);
// CTO下属
cto.add(techManager);
cto.add(qaEngineer);
// 技术经理下属
techManager.add(developer1);
techManager.add(developer2);
techManager.add(developer3);
// CFO下属
cfo.add(accountant1);
cfo.add(accountant2);
// HR经理下属
hrManager.add(recruiter);
hrManager.add(trainer);
// 显示组织架构
System.out.println("=== 公司组织架构 ===");
ceo.display(0);
// 统计信息
System.out.println("\n=== 组织统计 ===");
System.out.println("总员工数: " + ceo.getEmployeeCount() + "人");
System.out.println("总薪资支出: ¥" + ceo.getTotalSalary());
// 查找特定职位
System.out.println("\n=== 开发工程师列表 ===");
List<EmployeeComponent> developers = ceo.getEmployeesByPosition("中级开发工程师");
for (EmployeeComponent dev : developers) {
System.out.println("- " + dev.getName() + " (" + dev.getPosition() + ")");
}
}
}
浙公网安备 33010602011771号