C# 具有不同输入参数的类的工厂模式设计

C# 具有不同输入参数的类的工厂模式设计,c#,asp.net,.net,.net-core,factory-pattern,C#,Asp.net,.net,.net Core,Factory Pattern,我想在我的程序中实现工厂模式,但我不习惯。实现这种factory和Execute()方法的最佳实践是什么?这种方法将使用各种不同的参数调用其他方法 我有StepFactory.csclass public class ProcessStepFactory: IProcessStepFactory { private readonly ITable_table; private readonly ICompareTest _compareTest; public

我想在我的程序中实现工厂模式,但我不习惯。实现这种factory和Execute()方法的最佳实践是什么?这种方法将使用各种不同的参数调用其他方法

我有
StepFactory.cs
class

    public class ProcessStepFactory: IProcessStepFactory
{
    private readonly ITable_table;
    private readonly ICompareTest _compareTest;

    public ProcessStepFactory(ITable table, ICompareTest compareTest)
    {
        _table= table;
        _compareTest = table;
    }

    public IProcessStep CreateProcessStep(string stepName, FileInfo file, DateTime s, DateTime d, int id)
    {
        switch (stepName)
        {
            case "TABLE":
                return _table;
            case "COMPARE":
                return _compareTest;
            default:
                return null;
        }
    }
}
我在
switch
案例中使用的每个类都从
IStep接口实现
Execute()
方法

但是,每个类对此方法需要不同的参数,因为
Execute()
方法将用于调用其他方法,例如:

compareTest.cs

public class CompareTest : ICompareTest
{
    private readonly IORepository _Ora;
    private readonly IPRepository _Pg;
    private readonly IRRepository _rPg;

    public TableDataCompareTest(
        IORepository Ora,
        IPRepository Pg,
        IRRepository Pg)
    {
        _connOra = connOra;
        _connPg = connPg;
        _resultPg = resultPg;
    }

    public void Execute()
    {
        CompareTest(int id, DateTime s,  DateTime d)
    }

    public void CompareTest(int parentId, DateTime oraStart,  DateTime pgStart)
    {
       // do stuff
    }
}
表.cs

public class TableCountTest : ITableCountTest
{
    private readonly IORepository _Ora;
    private readonly IPRepository _Pg;
    private readonly IRRepository _rPg;

    public TableCountTest(IORepository Ora,
        IPRepository Pg,
        IRRepository Pg)
    {
        _connOra = connOra;
        _connPg = connPg;
        _resultPg = resultPg;
    }

    public void Execute()
    {
       Test(id);
    }

    public void Test(int id)
    {
       // do stuff
    }
}

具有所有类都将实现的
Execute()
方法的接口:

public interface IProcessStep
{
    void Execute();
}
另一个类的方法将需要
FileInfo文件
参数等等。
实现这样的工厂和将调用具有各种不同参数的其他方法的
Execute()
方法的最佳实践是什么?

对于工厂模式来说是新的,我的建议是每1个接口有1个工厂,然后根据它们的实际功能对它们进行命名,因此ExecuteTest1(int param1)、ExecuteTest2(int-param1,int-param2)等


除此之外,您正在寻找的是抽象的工厂模式。

我使用了策略模式。下面是有助于推进该模式的代码

 public class ProcessStepFactory : IProcessStepFactory
{
    private readonly ITableCountTest _table;
    private readonly ICompareTest _compareTest;
    private readonly IStrategyManager _manager; //code added
    public ProcessStepFactory(ITableCountTest table, ICompareTest compareTest,IStrategyManager manager)
    {
        _table = table;
        _compareTest = compareTest;
        _manager = manager;
    }

    public IProcessStep CreateProcessStep(string stepName, FileInfo file, DateTime s, DateTime d, int id)
    {
        return _manager.Process(stepName);
    }
}
这是新引进的班级

public interface IStrategyManager
{
    IProcessStep Process(string stepName);
}

public class StrategyManager : IStrategyManager
{
    private Dictionary<string, IProcessStep> dictionary = new Dictionary<string, IProcessStep>();

    public StrategyManager()
    {
        dictionary.Add("TABLE", new TableCountTest());
        dictionary.Add("COMPARE", new CompareTest());
    }

    public IProcessStep Process(string stepName)
    {
        return dictionary[stepName]; //returns the required object as per stepName
    }
}
以及第二个实现类CompareTest

public class CompareTest : ICompareTest, IProcessStep
{
    //... other code

    public void Execute()
    {
        /*   your logic goes here*/
    }
    public void Compare(int parentId, DateTime oraStart, DateTime pgStart)
    {
          // 
    }
}

希望能有所帮助。

您的
IStep
实现需要的所有这些参数,以及您当前正在传递给
ProcessStepFactory::CreateProcessStep()的参数,到底是什么
?假设它们不是完全独立的数据,并且实际上是您希望流程步骤在其上操作的某个对象或概念的不同属性,您可以定义一个类,将这些属性收集到单个单元中,然后定义
IStep::Execute()
及其实现,以接受该类或该类实现的接口的实例。例如:

public interface IProcessContext
{
    // Hopefully you're using more descriptive names than these in your actual code...
    FileInfo File { get; set; }
    DateTime S { get; set; }
    DateTime D { get; set; }
    int Id { get; set; }
}
您在问题中展示的示例
Execute()
方法如下所示:

// In TableCountTest:
public void Execute(IProcessContext context) =>
    Test(context.Id);

// In CompareTest:
public void Execute(IProcessContext context) =>
    Compare(context.Id, context.S, context.D);
现在,所有步骤“
Execute()
方法具有相同的签名,允许您通过一个公共接口调用它们,就像您要使用的一样。请注意,由于每个步骤都接收相同的
上下文
对象,因此理论上每个步骤都可以对其进行更改,后面的步骤可以建立在前面步骤已经完成的工作的基础上。这可能是有益的,但也可能是有益的这是一个缺点;步骤列表越长,上下文类越复杂,就越容易忘记在哪里设置或更改了什么。如果使用这种方法,我建议您仔细考虑上下文的哪些部分应该是可变的,哪些部分不应该是可变的


如果出于任何原因希望
Execute()
方法不采用问题中所示的参数,那么您可能需要修改
ProcessStepFactory::CreateProcessStep()
始终创建并返回相应的
IStep
的新实例,而不是使用共享实例,并指定如上所述的单个上下文对象或该方法现有参数列表的适当组合作为step对象的属性。

我已使用MEF创建并执行工厂模式ith接口。
// In TableCountTest:
public void Execute(IProcessContext context) =>
    Test(context.Id);

// In CompareTest:
public void Execute(IProcessContext context) =>
    Compare(context.Id, context.S, context.D);