我喜欢“编程接口”的概念,并避免使用“new”关键字。
但是,当我有两个具有相同界面但与设置根本不同的类时,我该怎么办。在没有详细介绍我的特定代码的情况下,我有一个方法接口,“DoStuff”。两个类实现此接口。一个非常简单,无需初始化即可。另一个有五个不同的变量需要设置。结合起来,当调用DoStuff时,它们允许数百万种类的方式工作。
那么我什么时候“新”这些课程呢?我虽然关于使用工厂,但由于设置的巨大差异,我不认为它们适用于这种情况。 (顺便说一句:实际上有大约十个不同的类使用接口,每个类允许形成复杂管道的一部分,每个类都有不同的配置要求)。
答案 0 :(得分:6)
我认为你可能误解了接口编程的概念。您始终必须在面向对象语言中使用new
关键字来创建对象的新实例。仅仅因为您对接口进行编程并不能消除该要求。
对接口进行编程只是意味着所有具体类的行为都在接口中定义,而不是在具体类本身中定义。因此,当您定义变量的类型时,您将其定义为接口而不是具体类型。
在您的情况下,只需在您的具体类中实现DoStuff
,因为每个类都需要它实现(无论是简单地还是使用其他10个初始化对象和设置)。例如,如果您有一个实现IInterface
的接口SomeClass
和类IInterface
。您可以声明SomeClass
的实例:
IInterface myInstance = new SomeClass();
这允许您将此实例传递给其他函数,而不必让这些函数担心该实例类的实现细节。
答案 1 :(得分:2)
嗯,你真的有3个选择。使用新的,使用工厂或使用DI容器。对于DI容器,您的五个变量很可能需要在某些类型的配置文件中。
但是说实话,听起来你似乎正在通过强迫自己进入角落来让你的生活更加艰难。而不是编写一些理想的代码,而是以最有利于解决手头问题的方式编写代码。不是说你应该做它的黑客工作,但实际上,说你不想使用新的,这真的让你的生活比你需要的更难......
答案 2 :(得分:1)
无论你使用什么,在某些时候你都必须构建你的类的实例才能使用它们,没有办法解决这个问题。
如何做到这一点取决于你想要完成什么,以及这些类的语义。
参加你提到的课程。
可以从某个地方读取这些字段吗?以配置文件为例?如果是这样,您可能只需要一个默认构造函数来从这样的配置文件初始化这些字段。
但是,如果这些字段的内容确实需要从外部传入,那就没办法了。
也许您应该查看IoC容器和依赖注入?
答案 3 :(得分:0)
如果您将许多配置参数传递到您的班级,那么它可能会承担太多责任。你应该考虑将它分解成只有一个责任的小类。
避免使用new关键字非常有价值,因为它会对实现类产生依赖性。更好的解决方案是使用Dependancy Injection。
例如
public interface IDoStuff
{
void DoStuff();
}
public class DoStuffService
{
private IDoStuff doer;
public DoStuffService()
{
//Class is now dependant on DoLotsOfStuff
doer = new DoLotsOfStuff(1,true, "config string");
}
}
public class DoStuffBetterService
{
private IDoStuff doer;
//inject dependancy - no longer dependant on DoLotsOfStuff
public DoStuffBetterService(IDoStuff doer)
{
this.doer = doer;
}
}
显然,您仍然需要创建在某处传递的IDoStuff对象。 控制反转(IoC)容器是帮助实现此功能的好工具。 如果您有兴趣了解更多内容,这是Castle Windsor Container的一个很好的教程。 (还有很多其他的IoC容器,我只是碰巧使用这个容器。)
你问题中的例子很抽象,所以我希望这个答案很有帮助。
答案 4 :(得分:0)
如果我理解正确,问题在于初始化不同。您需要提供两个具有相同接口的类。一个不需要任何东西,另一个需要一些参数并调用一些复杂的初始化。
您应该使用具有InitializationParameter的构造函数。两个班都应该得到它。一个简单的界面,不需要从中获取任何东西。另一个需要params并将从中获取它们。
如果你担心初始化你可以使用工厂,只需要它提供一个提供这个init参数的接口,工厂将根据你提供的值创建,初始化并返回给你。
如果不清楚 - 请询问。