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

实例化POCO类代码如何重构?POCO集合依赖耦合优化方案咨询

核心结论

你提到的「尽量避免在类中使用new关键字」的规范,适用场景是有业务逻辑、有外部依赖、需要支持单元测试替换实现的服务类,完全不适用纯数据POCO和类内部的临时状态集合。你想到的前两个方案属于典型的过度设计,第三个方案也存在逻辑漏洞,最优的重构方案如下:


现有问题排查

首先你当前的代码存在两个隐性bug:

  1. _visitedBranch作为类字段,若CustomerCountRequestProcessor以DI框架默认的单例模式注册,多次请求会共享同一个集合,上次请求的访问记录会导致本次请求误判循环分支、异常报错。
  2. 在GetCustomersForSelectedNode中重写类字段_network的操作存在并发风险,多线程同时调用时会互相覆盖_network的值,导致计算结果错误。

不合理方案说明

  • 「封装集合类+接口注入」:完全没有必要,_visitedBranch是单请求内的临时状态,不需要对外暴露也不需要替换实现,注入反而会因为生命周期管理不当引发共享状态冲突。
  • 「工厂类获取集合」:工厂的作用是封装复杂的实例创建逻辑、控制实例生成策略,你仅需要一个空的存储集合,没有复杂创建逻辑,工厂属于冗余代码。
  • 「集合初始化放构造函数」:依然没有解决单例模式下多请求共享集合的问题,只是把初始化位置移动了,核心bug没有修复。

最优重构方案

把访问集合从类字段改为单请求内的局部变量,用HashSet替代List提升存在性判断的性能(HashSet.Contains是O(1)复杂度,List.Any是O(n)复杂度),同时修正异常类型、解决并发问题:

public class CustomerCountRequestProcessor : ICustomerCountRequestProcessor
{
    private readonly INetwork _defaultNetwork;

    public CustomerCountRequestProcessor(INetwork defaultNetwork)
    {
        _defaultNetwork = defaultNetwork ?? throw new ArgumentNullException(nameof(defaultNetwork));
    }

    public int GetCustomersForSelectedNode(IRoot request)
    {
        if (request == null)
            throw new ArgumentNullException(nameof(request));

        var currentNetwork = request.Network ?? _defaultNetwork;
        // 每次请求新建独立的访问记录集合,和其他请求完全隔离
        var visitedBranches = new HashSet<(int StartNode, int EndNode)>();
        return ProcessSelectedNode(request.SelectedNode, currentNetwork, visitedBranches);
    }

    private int ProcessSelectedNode(int node, INetwork network, HashSet<(int StartNode, int EndNode)> visitedBranches)
    {
        var nodeCustomer = network.Customers.FirstOrDefault(c => c.Node == node);
        var customersForNode = nodeCustomer?.NumberOfCustomers ?? 0;

        foreach (var branch in network.Branches.Where(b => b.StartNode == node))
        {
            var branchKey = (branch.StartNode, branch.EndNode);
            if (visitedBranches.Contains(branchKey))
            {
                // 原逻辑抛出ArgumentNullException不符合错误场景,改为循环分支对应的异常类型
                throw new InvalidOperationException($"检测到循环分支:{branch.StartNode} -> {branch.EndNode}");
            }
            visitedBranches.Add(branchKey);
            customersForNode += ProcessSelectedNode(branch.EndNode, network, visitedBranches);
        }

        return customersForNode;
    }
}

如果一定要保留独立的Branch类,只需要给Branch重写Equals和GetHashCode方法,或者给HashSet传入自定义的IEqualityComparer<Branch>即可,不需要额外引入抽象层。


内容的提问来源于stack exchange,提问作者user16405900

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:30:02