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

新增消费者时如何避免RequestData类膨胀?

系统建模优化方案:解决RequestData膨胀与数据冗余问题

问题背景

现有系统包含多个请求处理器(如定价计算器),每个处理器仅依赖请求数据的子集,但所有处理器共享一个RequestData类。新增处理器时需修改RequestData添加字段,导致:

  • 类持续膨胀,复杂度升高
  • 多数处理器携带冗余数据,效率低下

原代码中的IRequestProcessor接口及各消费者实现、RequestData类存在上述耦合问题。

优化方案

1. 接口隔离原则(ISP):拆分数据契约

针对不同处理器的依赖,将RequestData拆分为多个粒度更细的接口,让每个处理器仅依赖自己需要的数据契约。

示例实现:

// 基础数据契约,所有处理器共享
public interface IBaseRequestData
{
    double BaseCost { get; }
}

// ConsumerA、B依赖的扩展数据契约
public interface IValueRequestData : IBaseRequestData
{
    double SomeValue { get; }
}

// ConsumerB额外依赖的条件数据契约
public interface IConditionRequestData : IValueRequestData
{
    bool SomeCondition { get; }
}

// ConsumerC、D依赖的详情数据契约
public interface IDetailRequestData : IBaseRequestData
{
    bool HasDetail { get; }
}

// ConsumerD额外依赖的期限数据契约
public interface IDueDateRequestData : IDetailRequestData
{
    DateTime DueDate { get; }
}

// 处理器仅依赖自身需要的接口
public class ConsumerA : IRequestProcessor
{
    public double ComputeResult(IValueRequestData request)
        => 10 * request.SomeValue + request.BaseCost;
}

public class ConsumerB : IRequestProcessor
{
    public double ComputeResult(IConditionRequestData request)
        => (request.SomeCondition ? 10 : 0) * request.SomeValue + request.BaseCost;
}

public class ConsumerC : IRequestProcessor
{
    public double ComputeResult(IDetailRequestData request)
        => request.HasDetail ? 1.5 * request.BaseCost : request.BaseCost;
}

public class ConsumerD : IRequestProcessor
{
    public double ComputeResult(IDueDateRequestData request)
        => request.DueDate < DateTime.Now.AddMonths(6) 
            ? -1 
            : request.HasDetail ? 1.5 * request.BaseCost : request.BaseCost;
}

// 完整请求类按需实现多个接口
public class FullRequestData : IConditionRequestData, IDueDateRequestData
{
    public double BaseCost { get; }
    public double SomeValue { get; }
    public bool SomeCondition { get; }
    public bool HasDetail { get; }
    public DateTime DueDate { get; }

    public FullRequestData(double baseCost, double someValue, bool someCondition, bool hasDetail, DateTime dueDate)
    {
        BaseCost = baseCost;
        SomeValue = someValue;
        SomeCondition = someCondition;
        HasDetail = hasDetail;
        DueDate = dueDate;
    }
}

优势:每个处理器仅依赖必要数据,新增处理器时只需定义新的数据接口,无需修改现有数据类,符合开闭原则。


2. 组合模式:分层数据模型

将请求数据拆分为多个独立的子数据类,通过组合方式构建完整请求,每个处理器按需获取子数据。

示例实现:

// 基础数据类
public class BaseRequestData
{
    public double BaseCost { get; }
    public BaseRequestData(double baseCost) => BaseCost = baseCost;
}

// 价值相关子数据
public class ValueData
{
    public double SomeValue { get; }
    public ValueData(double someValue) => SomeValue = someValue;
}

// 条件相关子数据
public class ConditionData
{
    public bool SomeCondition { get; }
    public ConditionData(bool someCondition) => SomeCondition = someCondition;
}

// 详情相关子数据
public class DetailData
{
    public bool HasDetail { get; }
    public DetailData(bool hasDetail) => HasDetail = hasDetail;
}

// 期限相关子数据
public class DueDateData
{
    public DateTime DueDate { get; }
    public DueDateData(DateTime dueDate) => DueDate = dueDate;
}

// 完整请求类通过组合子数据构建
public class RequestData
{
    public BaseRequestData BaseData { get; }
    public ValueData ValueData { get; }
    public ConditionData ConditionData { get; }
    public DetailData DetailData { get; }
    public DueDateData DueDateData { get; }

    // 构造器支持按需注入子数据,避免冗余
    public RequestData(BaseRequestData baseData, ValueData valueData = null, ConditionData conditionData = null, DetailData detailData = null, DueDateData dueDateData = null)
    {
        BaseData = baseData;
        ValueData = valueData;
        ConditionData = conditionData;
        DetailData = detailData;
        DueDateData = dueDateData;
    }
}

// 处理器按需访问子数据
public class ConsumerA : IRequestProcessor
{
    public double ComputeResult(RequestData request)
        => 10 * request.ValueData.SomeValue + request.BaseData.BaseCost;
}

public class ConsumerD : IRequestProcessor
{
    public double ComputeResult(RequestData request)
        => request.DueDateData.DueDate < DateTime.Now.AddMonths(6) 
            ? -1 
            : request.DetailData.HasDetail ? 1.5 * request.BaseData.BaseCost : request.BaseData.BaseCost;
}

优势:数据结构模块化,新增子数据类不影响现有代码,处理器仅访问需要的子数据,减少冗余。


3. 策略模式+数据适配

为每个处理器定义专属的DTO(数据传输对象),通过适配器将原始请求数据转换为处理器所需的DTO,避免直接依赖大而全的RequestData。

示例实现:

// 泛型处理器接口,接受专属DTO
public interface IRequestProcessor<T>
{
    double ComputeResult(T dto);
}

// ConsumerA专属DTO
public class ConsumerADto
{
    public double BaseCost { get; }
    public double SomeValue { get; }
    public ConsumerADto(double baseCost, double someValue)
    {
        BaseCost = baseCost;
        SomeValue = someValue;
    }
}

// ConsumerA实现
public class ConsumerA : IRequestProcessor<ConsumerADto>
{
    public double ComputeResult(ConsumerADto dto)
        => 10 * dto.SomeValue + dto.BaseCost;
}

// ConsumerD专属DTO
public class ConsumerDDto
{
    public double BaseCost { get; }
    public bool HasDetail { get; }
    public DateTime DueDate { get; }
    public ConsumerDDto(double baseCost, bool hasDetail, DateTime dueDate)
    {
        BaseCost = baseCost;
        HasDetail = hasDetail;
        DueDate = dueDate;
    }
}

// ConsumerD实现
public class ConsumerD : IRequestProcessor<ConsumerDDto>
{
    public double ComputeResult(ConsumerDDto dto)
        => dto.DueDate < DateTime.Now.AddMonths(6) 
            ? -1 
            : dto.HasDetail ? 1.5 * dto.BaseCost : dto.BaseCost;
}

// 适配器:转换原始数据为各处理器的DTO
public class RequestDataAdapter
{
    public ConsumerADto ToConsumerADto(RequestData request)
        => new ConsumerADto(request.BaseCost, request.SomeValue);

    public ConsumerDDto ToConsumerDDto(RequestData request)
        => new ConsumerDDto(request.BaseCost, request.HasDetail, request.DueDate);
}

// 调用示例
var originalRequest = new RequestData(...);
var adapter = new RequestDataAdapter();
var consumerA = new ConsumerA();
var resultA = consumerA.ComputeResult(adapter.ToConsumerADto(originalRequest));

优势:处理器与原始数据完全解耦,新增处理器只需添加对应的DTO和适配器方法,对现有代码无侵入性。


总结

以上方案均围绕单一职责原则和开闭原则设计,核心思路是将大而全的RequestData拆分为粒度更细的契约/模块,让每个组件仅依赖自身所需的数据。实际选型可根据系统复杂度、扩展性需求决定:

  • 若需要严格的契约隔离,优先选择接口隔离原则方案;
  • 若数据结构天然可拆分,组合模式更直观;
  • 若需完全解耦处理器与原始数据,策略+适配方案最灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:09:56