设计模式14-组合模式
定义
Composite Partern:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
场景
-
处理树形结构数据:如文件系统(文件和文件夹)、组织架构(部门和员工)、菜单系统(菜单项和子菜单)等。
-
需要统一操作单个对象和组合对象:当客户端代码需要对「单个元素」和「元素集合」执行相同操作时(如计算总大小、展示信息等)。
-
动态构建层次结构:需要灵活地增加 / 删除层级节点,且不影响客户端对结构的使用。
代码
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;}@Overridepublic void add(DepartmentComponent component) {children.add(component);}@Overridepublic void remove(DepartmentComponent component) {children.remove(component);}@Overridepublic 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);}}@Overridepublic int getEmployeeCount() {// 计算本部门总员工数(所有子部门员工数之和)int total = 0;for (DepartmentComponent child : children) {total += child.getEmployeeCount();}return total;}@Overridepublic 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;}@Overridepublic void add(DepartmentComponent component) {// 叶子节点不能添加子部门throw new UnsupportedOperationException("基础部门不能包含子部门");}@Overridepublic void remove(DepartmentComponent component) {// 叶子节点没有子部门可移除throw new UnsupportedOperationException("基础部门没有子部门可移除");}@Overridepublic 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());}@Overridepublic int getEmployeeCount() {return employeeCount;}@Overridepublic 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);}
}
组合模式代码