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

工厂模式替代方案:根据文件扩展名选择构造不同的进程类

嘿,这个问题我之前也踩过类似的坑——当子类构造函数签名不一样时,常规的简单工厂确实会显得束手束脚。不过有几个很实用的方案可以解决这个问题,我给你梳理下:

方案1:参数对象+工厂方法(最推荐,兼顾清晰与灵活)

核心思路是把不同子类需要的构造参数,统一封装成一个参数对象,让工厂只需要传递这个对象,子类自己从里面提取需要的信息。这样不管子类构造函数差异多大,工厂的接口都是统一的。

举个代码示例:

// 基类
public abstract class BaseProcess
{
    public abstract void Start();
}

// 参数对象,包含所有可能需要的参数
public class ProcessCreationParams
{
    public string ExecutablePath { get; set; }
    public IntPtr ParentProcessHandle { get; set; }
    // 其他可能的参数:命令行参数、工作目录等
}

// 独立进程子类
public class IndependentProcess : BaseProcess
{
    private readonly string _execPath;
    public IndependentProcess(ProcessCreationParams @params)
    {
        _execPath = @params.ExecutablePath;
        // 这里只用到自己需要的参数
    }

    public override void Start()
    {
        // 启动独立进程逻辑
    }
}

// 依赖进程子类
public class DependentProcess : BaseProcess
{
    private readonly IntPtr _parentHandle;
    private readonly string _execPath;
    public DependentProcess(ProcessCreationParams @params)
    {
        _parentHandle = @params.ParentProcessHandle;
        _execPath = @params.ExecutablePath;
        // 用到父进程句柄和路径
    }

    public override void Start()
    {
        // 依赖父进程启动的逻辑
    }
}

// 工厂类
public static class ProcessFactory
{
    public static BaseProcess CreateProcess(string fileExtension, ProcessCreationParams @params)
    {
        return fileExtension.ToLower() switch
        {
            ".exe" => new IndependentProcess(@params),
            ".dll" => new DependentProcess(@params),
            _ => throw new NotSupportedException($"不支持的扩展名:{fileExtension}")
        };
    }
}

这种方式的好处是:工厂接口始终稳定,后续新增子类只需要扩展参数对象(如果需要新参数)和工厂的switch分支,代码可读性也很强。

方案2:抽象工厂模式(适合复杂扩展场景)

如果你的系统后续可能会新增更多类型的进程,或者每个进程类型还需要配套的其他对象(比如进程配置器、日志器),抽象工厂会是更好的选择。

简单来说,先定义一个抽象工厂接口,每个具体工厂对应一种进程类型,负责创建该类型的实例并处理自己的构造参数:

// 抽象工厂
public interface IProcessFactory
{
    BaseProcess CreateProcess(object[] args);
}

// 独立进程工厂
public class IndependentProcessFactory : IProcessFactory
{
    public BaseProcess CreateProcess(object[] args)
    {
        // 这里明确要求参数是可执行路径
        if (args.Length != 1 || args[0] is not string execPath)
            throw new ArgumentException("独立进程需要传入可执行路径");
        
        return new IndependentProcess(execPath);
    }
}

// 依赖进程工厂
public class DependentProcessFactory : IProcessFactory
{
    public BaseProcess CreateProcess(object[] args)
    {
        // 这里要求参数是父进程句柄和可执行路径
        if (args.Length != 2 || args[0] is not IntPtr parentHandle || args[1] is not string execPath)
            throw new ArgumentException("依赖进程需要传入父进程句柄和可执行路径");
        
        return new DependentProcess(parentHandle, execPath);
    }
}

// 工厂的注册表/调度器
public static class ProcessFactoryDispatcher
{
    private static readonly Dictionary<string, IProcessFactory> _factories = new()
    {
        { ".exe", new IndependentProcessFactory() },
        { ".dll", new DependentProcessFactory() }
    };

    public static BaseProcess CreateProcess(string fileExtension, params object[] args)
    {
        if (!_factories.TryGetValue(fileExtension.ToLower(), out var factory))
            throw new NotSupportedException($"不支持的扩展名:{fileExtension}");
        
        return factory.CreateProcess(args);
    }
}

这种方式把不同进程的创建逻辑完全解耦,每个具体工厂只关心自己的参数要求,后续扩展新进程只需要新增对应的工厂类和注册项即可。

方案3:委托注册表(灵活度拉满,适合小项目或快速迭代)

如果你的场景比较简单,不想写太多工厂类,可以用委托来实现动态注册。本质上是把创建实例的逻辑封装成委托,存在字典里:

public static class ProcessDelegateFactory
{
    private static readonly Dictionary<string, Func<object[], BaseProcess>> _creationDelegates = new()
    {
        { ".exe", args => new IndependentProcess((string)args[0]) },
        { ".dll", args => new DependentProcess((IntPtr)args[0], (string)args[1]) }
    };

    public static BaseProcess CreateProcess(string fileExtension, params object[] args)
    {
        if (!_creationDelegates.TryGetValue(fileExtension.ToLower(), out var createFunc))
            throw new NotSupportedException($"不支持的扩展名:{fileExtension}");
        
        return createFunc(args);
    }
}

这种方式代码量最少,但要注意类型安全——调用时必须传入正确类型和数量的参数,否则会抛出运行时异常。适合小项目或者快速验证想法的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:52:47