定义
Composite Partern:将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
场景
-
处理树形结构数据:如文件系统(文件和文件夹)、组织架构(部门和员工)、菜单系统(菜单项和子菜单)等。
-
需要统一操作单个对象和组合对象:当客户端代码需要对「单个元素」和「元素集合」执行相同操作时(如计算总大小、展示信息等)。
-
动态构建层次结构:需要灵活地增加 / 删除层级节点,且不影响客户端对结构的使用。
代码
java
import java.util.ArrayList;
import java.util.List;
// 组合节点:复合部门(可以包含子部门)
public class CompositeDepartment implements DepartmentComponent {
private String name;
private List<DepartmentComponent> children = new ArrayList<>();
public CompositeDepartment(String name) {
this.name = name;
}
@Override
public void add(DepartmentComponent component) {
children.add(component);
}
@Override
public void remove(DepartmentComponent component) {
children.remove(component);
}
@Override
public void display(int depth) {
// 显示部门信息,并递归显示所有子部门
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(" ");
}
sb.append("+ ").append(name).append(" (总员工数: ").append(getEmployeeCount()).append(")");
System.out.println(sb.toString());
// 递归显示子部门
for (DepartmentComponent child : children) {
child.display(depth + 1);
}
}
@Override
public int getEmployeeCount() {
// 计算本部门总员工数(所有子部门员工数之和)
int total = 0;
for (DepartmentComponent child : children) {
total += child.getEmployeeCount();
}
return total;
}
@Override
public String getName() {
return name;
}
}
// 部门组件接口:定义所有部门组件的共同行为
interface DepartmentComponent {
// 添加子部门
void add(DepartmentComponent component);
// 移除子部门
void remove(DepartmentComponent component);
// 显示部门信息
void display(int depth);
// 获取部门员工数量
int getEmployeeCount();
// 获取部门名称
String getName();
}
// 叶子节点:基础部门(不能包含子部门)
class LeafDepartment implements DepartmentComponent {
private String name;
private int employeeCount;
public LeafDepartment(String name, int employeeCount) {
this.name = name;
this.employeeCount = employeeCount;
}
@Override
public void add(DepartmentComponent component) {
// 叶子节点不能添加子部门
throw new UnsupportedOperationException("基础部门不能包含子部门");
}
@Override
public void remove(DepartmentComponent component) {
// 叶子节点没有子部门可移除
throw new UnsupportedOperationException("基础部门没有子部门可移除");
}
@Override
public void display(int depth) {
// 显示部门信息,使用depth控制缩进
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(" ");
}
sb.append("- ").append(name).append(" (员工数: ").append(employeeCount).append(")");
System.out.println(sb.toString());
}
@Override
public int getEmployeeCount() {
return employeeCount;
}
@Override
public String getName() {
return name;
}
}
// 演示部门树形结构的使用
class DepartmentHierarchyDemo {
public static void main(String[] args) {
// 创建公司顶级部门
CompositeDepartment company = new CompositeDepartment("总公司");
// 创建一级部门
CompositeDepartment techDepartment = new CompositeDepartment("技术部");
CompositeDepartment marketingDepartment = new CompositeDepartment("市场部");
CompositeDepartment adminDepartment = new CompositeDepartment("行政部");
// 向技术部添加二级部门
techDepartment.add(new LeafDepartment("前端开发组", 12));
techDepartment.add(new LeafDepartment("后端开发组", 18));
// 创建三级部门结构
CompositeDepartment productDepartment = new CompositeDepartment("产品研发中心");
productDepartment.add(new LeafDepartment("产品设计组", 5));
productDepartment.add(new LeafDepartment("测试组", 8));
productDepartment.add(new LeafDepartment("运维组", 6));
// 将产品研发中心添加到技术部(成为二级部门)
techDepartment.add(productDepartment);
// 向市场部添加二级部门
marketingDepartment.add(new LeafDepartment("市场推广组", 6));
marketingDepartment.add(new LeafDepartment("销售组", 20));
// 向行政部添加二级部门
adminDepartment.add(new LeafDepartment("人力资源组", 4));
adminDepartment.add(new LeafDepartment("财务组", 5));
adminDepartment.add(new LeafDepartment("行政后勤组", 3));
// 将一级部门添加到公司
company.add(techDepartment);
company.add(marketingDepartment);
company.add(adminDepartment);
// 展示整个部门层级结构
System.out.println("公司部门层级结构:");
company.display(0);
}
}