默认构造函数在不需要时无需初始化依赖项

时间:2019-04-30 13:33:36

标签: c#

我有两种类型,即AdditionCalcAggregateCalc,它们有两种方法:

  1. 计算:返回模型。 没有版本代码。
  2. 计算:不返回任何内容。 包括版本控制代码。将数据存储在数据库中。

代码:

public abstract class BaseCalculator 
{
     private readonly IVersion _version;
     protected BaseCalculator(IVersion version)
     {
            this._version = version;
     }
     public void Calculate(Request r)
     {
          CalculateInternal();
          //version code here
     }
     protected abstract void CalculateInternal(Request r);
     public abstract StatisticsModel Calculate(StatisticsRequest model);
}

public class AdditionCalc : BaseCalculator
{
    public AdditionCalc() : base(new Version(ConfigurationManager.ConnectionStrings["dbConnectionString"].ConnectionString)) { }
    public override StatisticsModel Calculate(StatisticsRequest model)
    {
         //no version code here
    }
}

public class CalculatorFactory
{
    public BaseCalculator GetCalculatorByType(int type)
    {
        switch (type)
        {
            case (int)Types.Addition:
                return new AdditionCalc();
            case (int)Types.Aggregate:
                return new AggregateCalc();
        }
    }
}

现在的问题是当我调用返回Calculate的{​​{1}}方法时,我不想调用基本构造函数,因为对于此方法,我不需要版本代码,但是每次调用此方法,默认构造函数将被调用并初始化StatisticsModel

这就是我调用适当的version variable of base class方法的方式:

Calculate

注意:我不想通过调用代码传递版本依赖项

那么我该如何设计以上代码,以使不会为返回var calculatorFactory = new CalculatorFactory(); var type = calculatorFactory.GetCalculatorByType((int)Types.Addition); type.Calculate(StatisticsRequest); 的{​​{1}}方法调用Version代码?

更新:

Calculate

4 个答案:

答案 0 :(得分:3)

您的两个计算器类不应相互关联。它们应该实现一个通用的接口,但不共享通用的逻辑。

因此,您将有一类支持版本控制的东西,而另一类对版本控制一无所知。每个对象都100%专注于自己的逻辑,而不必彼此耦合/关联或交互。

如果您以后确实有一些常见行为,请确保它确实是常见行为,并将其放在两个类都继承的基类中。

到现在为止,您将覆盖版本控制行为(甚至不完全)。使用继承时,您想添加功能,而不是减去功能,这就是您当前模型正在做的事情。

看看SOLID以获得更多指导。

考虑,

interface ICalculator
{
    void Calculate() { ... }
}

abstract class CalculatorThatCaresAboutVersion : ICalculator
{
    void CalculatorThatCaresAboutVersion(IVersion version) { ... }
}

abstract class CalculatorThatDoesntCareAboutVersion : ICalculator
{
    void CalculatorThatDoesntCareAboutVersion() { ... }
}

您有两种不知道或不在乎其他种类的计算器。您可以根据需要从它们那里继承,并且与版本关联的操作与其他计算器中的操作没有任何关系。

这使您可以自由地按需实现每个对象,而又不影响其他对象:没有诸如“如果我不关心它该如何初始化版本”之类的问题?由于自然存在关注点分离,因此问题甚至根本不会出现

答案 1 :(得分:1)

如果我没记错的话,您只需要Calculate(Request r)的版本,而不需要Calculate(StatisticsRequest model)的版本

此外,您还可以将依赖项隐藏在您使用的类中,即您不希望客户端代码通过版本(这可能不是一个好主意)。

如何删除IVersion的{​​{1}}参数并在BaseCalculator方法中检索所需的值? 像这样:

Calculate

受保护的public abstract class BaseCalculator { private readonly IVersion _version; protected BaseCalculator() { } public void Calculate(Request r) { this._version = GetVersion(); CalculateInternal(); //version code here } protected virtual void GetVersion() //protected virtual or abstract, pick the best for your scenario. { return new Version(ConfigurationManager.ConnectionStrings["dbConnectionString"].ConnectionString); } protected abstract void CalculateInternal(Request r); public abstract StatisticsModel Calculate(StatisticsRequest model); } 方法可以在派生类中重写(或者,如果您的GetVersion不知道如何创建BaseCalculator对象,则可以是抽象方法,强制派生类提供实施方案。

答案 2 :(得分:1)

您要解释的内容听起来像 optional 依赖项。

在不显着改变设计的情况下解决该问题的一种方法是将IVersion的创建推迟到真正需要的时候,方法是将IVersion的构造函数参数替换为某种工厂,例如{{ 1}},如果只需要创建一次,则最终将其与Func<IVersion>字段组合。

例如像这样的东西:

Lazy<T>

以及需要public abstract class BaseCalculator { private readonly Func<IVersion> _versionFactory; protected BaseCalculator(Func<IVersion> versionFactory) { _versionFactory = versionFactory; } }

的方法中
IVersion

var version = _versionFactory();
// version code here

public abstract class BaseCalculator 
{
    private readonly Lazy<IVersion> _version;
    protected BaseCalculator(Func<IVersion> versionFactory)
    {
        _version = new Lazy<IVersion>(versionFactory);
    }
}    

在两种情况下,派生类的构造函数代码都将是这样的(只需在当前基础调用代码之前添加var version = _version.Value; // version code here

() =>

答案 3 :(得分:0)

要实现的目标将需要覆盖无法完成的基本构造函数,请参见this post