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

如何重构代码将更多方法实现移至基类,仅保留SendRequest在子类?

解决方案:用工厂方法模式复用基类逻辑

你的思路完全正确——工厂模式正好能解决这个问题:既把重复的样板代码(比如DoThingOne里创建请求、赋值参数的逻辑)抽到基类,又不会让库项目被各个子类的Request特性污染。下面是具体的实现步骤:

1. 修改库项目的基类,添加工厂方法

我们在ThingDoerBase里新增一个抽象的工厂方法,让子类负责创建具体的IRequest<T>实例。这样基类就不用关心Request的具体实现,只依赖干净的IRequest<T>接口:

interface IDoStuff { 
    string DoThingOne<T>(T genericParm); 
    string DoThingOne<T>(T genericParm, int anotherParm); 
    string SendRequest<T>(IRequest<T> request); 
} 

interface IRequest<T> { 
    T GenericParm { get; set; } 
    int IntParm { get; set; } 
} 

abstract class ThingDoerBase : IDoStuff { 
    // 保留原有的默认参数实现
    public virtual string DoThingOne<T>(T parm) => DoThingOne(parm, 25); 

    // 把抽象方法改成虚方法,复用创建请求的核心逻辑
    public virtual string DoThingOne<T>(T parm, int anotherParm) {
        // 调用子类实现的工厂方法创建请求
        var req = CreateRequest<T>();
        req.GenericParm = parm;
        req.IntParm = anotherParm;
        return SendRequest(req);
    } 

    // 新增抽象工厂方法,由子类提供具体Request的创建逻辑
    protected abstract IRequest<T> CreateRequest<T>();

    public abstract string SendRequest<T>(IRequest<T> request); 
} 

2. 修改实现项目,仅实现必要方法

现在子类只需要完成两件事:实现CreateRequest<T>返回自己的Request实例,以及SendRequest的具体业务逻辑,所有DoThingOne的通用逻辑都留在基类里:

Implement1项目示例

class Imp1Request<T> : IRequest<T> { 
    [JsonProperty("_GenericParm")]
    public T GenericParm { get; set; } 
    public int IntParm { get; set; } 
} 

class ThingDoer : ThingDoerBase { 
    // 只需要实现工厂方法,返回Imp1Request实例
    protected override IRequest<T> CreateRequest<T>() {
        return new Imp1Request<T>();
    }

    public override string SendRequest<T>(IRequest<T> req) {
        // 这里写Implement1的具体请求发送逻辑
        return $"Imp1 sent request with parm: {req.GenericParm}, int: {req.IntParm}";
    } 
} 

Implement2项目示例

同理,Implement2可以轻松实现自己的Request和工厂方法,完全不影响库项目:

class Imp2Request<T> : IRequest<T> { 
    [XmlAttribute("StringParm")]
    public T GenericParm { get; set; } 
    public int IntParm { get; set; } 
} 

class ThingDoerImp2 : ThingDoerBase { 
    protected override IRequest<T> CreateRequest<T>() {
        return new Imp2Request<T>();
    }

    public override string SendRequest<T>(IRequest<T> req) {
        // Implement2的具体请求发送逻辑
        return $"Imp2 sent XML request with parm: {req.GenericParm}, int: {req.IntParm}";
    } 
} 

为什么这个方案适合你?

  • 最大化复用代码:DoThingOne里创建请求、赋值参数的逻辑完全收拢到基类,子类不用重复写这些样板代码。
  • 避免污染库项目:每个子类的Request特性(比如JsonProperty、XmlAttribute)都留在各自的实现项目里,库项目只依赖纯净的IRequest<T>接口。
  • 扩展性极强:以后新增Implement3,只需要实现自己的Request和工厂方法即可,基类不需要任何修改。

如果后续需要更灵活的Request创建逻辑(比如依赖注入),也可以把工厂类单独抽出来,但对于当前场景,基类里的抽象工厂方法已经足够简洁好用了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:58:59