You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

适配开闭原则:从Company层级复杂对象提取信息的设计模式选型

推荐使用访问者模式(Visitor Pattern)

嘿,这个场景访问者模式绝对是为你量身打造的!它完美契合你所有的要求——不用修改Company、Department、Employee这些业务对象,新增提取需求只需要创建新类,完全遵循开闭原则。

为什么它适合你的场景?

访问者模式的核心就是把稳定的数据结构(你的Company/Department/Employee层级结构)和多变的操作逻辑(提取男性员工、筛选加拿大部门这类需求)彻底分离。你的业务对象结构是固定的,但提取需求会不断新增,这正好是访问者模式的典型适用场景。

大概怎么实现?

我给你理个简单的实现思路:

  1. 定义访问者接口:为每个业务对象声明对应的访问方法,比如visitCompany(Company)、visitDepartment(Department)、visitEmployee(Employee)。
  2. 业务类添加接受方法:在Company、Department、Employee里各加一个accept(Visitor)方法,方法内部调用访问者对应的visit方法并传入自身——比如Company的accept就是让访问者来访问自己,再遍历所有部门让它们也接受访问。
  3. 为每个需求创建具体访问者:
    • 比如要提取男性员工,就写个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:35:10