4

我喜欢“为接口编程”的想法,并避免使用“new”关键字。

但是,当我有两个具有相同接口但设置根本不同的类时,我该怎么办。在不详细介绍我的特定代码的情况下,我有一个带有方法“DoStuff”的接口。两个类实现了这个接口。一个非常简单,不需要初始化。另一个有五个不同的变量需要设置。当它们组合在一起时,当调用 DoStuff 时,它们允许类以数百万种方式工作。

那么我什么时候“新”这些课程呢?我虽然关于使用工厂,但我认为它们不适合这种情况,因为设置存在巨大差异。(顺便说一句:实际上有大约十个不同的类使用该接口,每个类都允许形成复杂管道的一部分,并且每个类都有不同的配置要求)。

4

5 回答 5

6

我认为您可能误解了对接口进行编程的概念。您总是必须new在面向对象的语言中使用关键字来创建对象的新实例。仅仅因为您对接口进行编程并不能消除该要求。

对接口进行编程仅仅意味着所有具体类的行为都在接口中定义,而不是在具体类本身中定义。因此,当您定义变量的类型时,您将其定义为接口而不是具体类型。

在您的情况下,只需DoStuff在您的具体类中实现,因为每个类都需要实现(无论是简单地实现还是使用其他 10 个初始化对象和设置)。例如,如果您有IInterface一个SomeClass实现IInterface. 你可以SomeClass这样声明一个实例:

IInterface myInstance = new SomeClass();

这允许您将此实例传递给其他函数,而不必让这些函数担心该实例类的实现细节。

于 2009-05-10T20:34:10.067 回答
2

那么你真的有3个选择。使用新的、使用工厂或使用 DI 容器。使用 DI 容器,您的五个变量很可能需要位于某种配置文件中。

但老实说,这听起来像是你把自己逼到角落里,让你的生活变得比需要的更艰难。与其按照某种理想进行编码,不如以最有助于解决手头问题的方式进行编码。不是说你应该对它进行破解,而是说你不想使用新的,这真的让你的生活变得比它需要的更难......

于 2009-05-10T20:43:47.477 回答
1

不管你使用什么,在某些时候你将不得不构造你的类的实例才能使用它们,这是没有办法的。

如何去做这取决于你想要完成什么,以及这些类的语义。

参加你提到的那些领域的课程。

可以从某个地方读取这些字段吗?一个配置文件,例如?如果是这样,也许您所需要的只是一个默认构造函数,它从这样的配置文件中初始化这些字段。

但是,如果这些字段的内容真的需要从外部传入,那就没有办法了。

也许你应该看看 IoC 容器和依赖注入?

于 2009-05-10T20:31:18.200 回答
0

如果您将这么多配置参数传递到您的类中,它可能有太多责任。您应该考虑将其分解为仅具有单一职责的较小类。

避免使用 new 关键字可能很有价值,因为它会产生对实现类的依赖。更好的解决方案是使用依赖注入。

例如

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 容器,我只是碰巧使用了这个。)

您问题中的示例非常抽象,所以我希望这个答案会有所帮助。

于 2009-05-11T19:33:13.993 回答
0

如果我理解正确,问题在于不同的初始化。您需要提供两个具有相同接口的类。一个不需要任何东西,另一个需要一些参数并调用一些复杂的初始化。

您应该使用获取 InitializationParameter 的构造函数。两个班级都应该得到它。一个具有简单界面的界面,不需要从中获取任何内容。另一个需要参数并将从中获取它们。

如果您担心初始化,您可以使用工厂,只需向它询问一些提供此 init 参数的接口,工厂将根据您提供的值创建、初始化并返回对象。

如果有什么不清楚 - 请询问。

于 2009-08-20T15:58:41.167 回答