有时在设计类时,我需要一些具有相似构造函数参数的依赖类。假设我们有
interface IDependency {
void DoSomething();
}
class DependencyClass : IDependency {
public DependencyClass(int length) {...}
...
}
class MainClass {
public MainClass(int length, IDependency dependency) {...}
...
}
MainClass
需要具有相同DependencyClass
的{{1}}实例。我有两种处理方法:
不直接创建length
的实例,而总是从工厂获取它们。这样,我可以确保将所需的MainClass
实例提供给IDependency
构造函数。
将工厂接口(例如MainClass
而不是IDependencyFactory
传递给MainClass
构造函数。这样我就可以在自己的IDependency
实现中获取DependencyClass
的所需实例。
我不确定它们中的任何一个是否是一个不错的选择。在这种情况下是否有最佳做法?
答案 0 :(得分:5)
这是一个非常有趣的问题,答案取决于您在此处尝试实现的目标。
解决方案1。。您提供的IDependency
将成为工厂的主要接口,所有实例将通过IDependency
接口实现,这将为您提供很多可扩展性-将来,您将可以使用IDependency
接口使用不同的功能来初始化其他类,这是工厂设计模式的经典用法和实现。
解决方案2 。您提供的MainClass
将使程序的Main Class变得更好,您将在Main Class中处理实例及其行为,这样做的好处是您可以通过IDependency
管理所有实例,而在MainClass
中要做的唯一事情就是处理它们的逻辑,MinaClass
将是您的实例传输器,以及对基础的所有基本更改将在接口IDependency
中创建类,这是依赖倒置的经典解决方案。
问题仍然存在,您要实现什么目标。考虑一下这个问题和两种可能性,您就会得到答案。
答案 1 :(得分:3)
如果您的length
是运行时变量,请参考this comment。
如果在运行时需要此功能,则可以使用this answer中的解决方案#2。
如果它是编译时间设置,则可以将其作为任何其他依赖项注入,这MainClass
和DependencyClass
都依赖于同一值是正常的。
要获得安全的编译时注入,可以引入如下内容:
interface ILength {
int Length { get; }
}
class StaticLength : ILength {
public StaticLength(int length) {
Length = length;
}
}
void Main() {
const int length = 10;
ILength lengthDependency = new StaticLength(length);
IDependency dep = new DependencyClass(lengthDependency);
MainClass mainClass = new MainClass(lengthDependency, dep);
}
现在您可以实现任何种类的ILength
-从配置文件,常量,Web,模拟,基于其他任何依赖项,随机值的计算中读取。
答案 2 :(得分:3)
为保证DepencyClass
和MainClass
的长度相同,您可以做的最简单的更改之一就是在接口中添加一个Length
属性并对其进行初始化。从构造函数中访问,然后允许MainClass
访问长度(然后在MainClass
上保存一个参数,该参数将更多DRY。
interface IDependency {
int Length { get; }
void DoSomething();
}
class DependencyClass : IDependency {
public DependencyClass(int length) { Length = length; }
...
}
class MainClass {
public MainClass(IDependency dependency) {...}
...
// do something with dependency.Length
}
这确实有可能会“污染”您的界面,并可能使长度暴露给其他代码。如果那很重要,则取决于您。