适配开闭原则:从Company层级复杂对象提取信息的设计模式选型
推荐使用访问者模式(Visitor Pattern)
嘿,这个场景访问者模式绝对是为你量身打造的!它完美契合你所有的要求——不用修改Company、Department、Employee这些业务对象,新增提取需求只需要创建新类,完全遵循开闭原则。
为什么它适合你的场景?
访问者模式的核心就是把稳定的数据结构(你的Company/Department/Employee层级结构)和多变的操作逻辑(提取男性员工、筛选加拿大部门这类需求)彻底分离。你的业务对象结构是固定的,但提取需求会不断新增,这正好是访问者模式的典型适用场景。
大概怎么实现?
我给你理个简单的实现思路:
- 定义访问者接口:为每个业务对象声明对应的访问方法,比如
visitCompany(Company)、visitDepartment(Department)、visitEmployee(Employee)。 - 业务类添加接受方法:在Company、Department、Employee里各加一个
accept(Visitor)方法,方法内部调用访问者对应的visit方法并传入自身——比如Company的accept就是让访问者来访问自己,再遍历所有部门让它们也接受访问。 - 为每个需求创建具体访问者:
- 比如要提取男性员工,就写个
MaleEmployeeVisitor,在visitEmployee方法里判断性别并收集符合条件的员工; - 要找加拿大的部门,就写个
CanadaDepartmentVisitor,在visitDepartment方法里判断地区并收集。
- 比如要提取男性员工,就写个
举个代码示例(Java风格)
// 第一步:定义访问者接口 interface CompanyVisitor { void visitCompany(Company company); void visitDepartment(Department department); void visitEmployee(Employee employee); } // 第二步:给业务类添加accept方法 class Company { private List<Department> departments; public void accept(CompanyVisitor visitor) { visitor.visitCompany(this); // 让所有部门也接受访问 departments.forEach(dept -> dept.accept(visitor)); } } class Department { private String region; private List<Employee> employees; public void accept(CompanyVisitor visitor) { visitor.visitDepartment(this); // 让所有员工也接受访问 employees.forEach(emp -> emp.accept(visitor)); } // getter方法 public String getRegion() { return region; } } class Employee { private String gender; public void accept(CompanyVisitor visitor) { visitor.visitEmployee(this); } // getter方法 public String getGender() { return gender; } } // 第三步:具体访问者——提取所有男性员工 class MaleEmployeeVisitor implements CompanyVisitor { private final List<Employee> maleEmployees = new ArrayList<>(); @Override public void visitCompany(Company company) { // 这里不需要额外操作,因为Company已经会遍历部门了 } @Override public void visitDepartment(Department department) { // 同理,Department会遍历员工 } @Override public void visitEmployee(Employee employee) { if ("Male".equals(employee.getGender())) { maleEmployees.add(employee); } } // 对外提供获取结果的方法 public List<Employee> getMaleEmployees() { return maleEmployees; } } // 使用示例 public class Main { public static void main(String[] args) { Company myCompany = buildMyCompany(); // 构造你的公司对象 MaleEmployeeVisitor maleVisitor = new MaleEmployeeVisitor(); myCompany.accept(maleVisitor); List<Employee> allMaleStaff = maleVisitor.getMaleEmployees(); } }
这样做的优势
- 严格遵循开闭原则:以后要加任何新的提取需求,比如“找薪资超过10k的员工”“找有超过20人的部门”,只需要新建一个Visitor实现类,完全不用碰原有业务对象的代码。
- 逻辑集中易维护:每个提取需求的逻辑都封装在单独的类里,不会把各种判断逻辑散落在业务对象中,代码更清晰,也方便单独测试。
内容的提问来源于stack exchange,提问作者pmartin8
相关产品推荐
相关产品推荐

