接口与继承:在这种情况下哪个更好?

时间:2010-08-11 05:45:59

标签: c# inheritance interface

假设我有一个小部件类:

struct Widget {
    public Color Color { get; set; }
    public int Frobbles { get; set; }
}

现在,我需要创建一个工厂来创建这些小部件,所以我构建了一个WidgetFactory:

abstract class WidgetFactory {
    public virtual Widget GetWidget();
}

事实证明,你可以用几种不同的材料制作小部件,但结果小部件几乎是一样的。所以,我有一些WidgetFactory的实现:

class GoldWidgetFactory : WidgetFactory {
    public GoldWidgetFactory(GoldMine goldmine) {
        //...
    }

    public Widget GetWidget() {
        Gold g = goldmine.getGold();
        //...
    }
}

class XMLWidgetFactory : WidgetFactory {
    public XMLWidgetFactory(XmlDocument xmlsource) {
        //...
    }

    public Widget GetWidget() {
        XmlNode node = //whatever
        //...
    }
}

class MagicWidgetFactory : WidgetFactory {
    public Widget GetWidget() {
        //creates widget from nothing
    }
}

我的问题是:WidgetFactory应该是一个抽象类还是一个接口?我可以在两个方向看到论点:

基类:

  • 实施ARE WidgetFactories
  • 他们可能能够共享功能(例如,List<Widget> WidgetFactory.GetAllWidgets()方法)

接口:

  • 实现不会从父
  • 继承任何数据或功能
  • 他们的内部运作完全不同
  • 只定义了一种方法

对于那些回答的人来说,这并不(目前)与任何现实世界的问题并行,但如果/当我需要实现这种模式时,最好知道。此外,“无所谓”是一个有效的答案。

编辑:我应该指出为什么要首先考虑这个问题。这个类层次结构的假设用法类似于:

//create a widget factory
WidgetFactory factory = new GoldWidgetFactory(myGoldMine);

//get a widget for our own nefarious purposes
Widget widget = factory.GetWidget();

//this method needs a few widgets
ConsumeWidgets(factory);

因此,在WidgetFactory中使用GetGoldWidget()方法并不是一个好主意。另外,Widget技术的出现也许让我们在未来添加不同的,更奇特的小部件类型?添加一个新类来处理它们比将现有类中的方法变为现有类更简单,更清晰。

4 个答案:

答案 0 :(得分:5)

在您给出WidgetFactory的示例中,绝对没有理由成为抽象类,因为工厂的不同实现之间没有共享属性或方法。

即使有共享功能,创建一个接口并将其传递给WidgetFactory的用户也会更加惯用,以减少这些组件对工厂所需的知识量。

整体实施很好,实际上是abstract factory pattern,我唯一要做的就是IWidgetFactory

public interface IWidgetFactory {
    Widget GetWidget();
}

abstract class WidgetFactory : IWidgetFactory {
    //common attributes and methods
}

//Defferent implementations can still inherit from the base abstract class
class GoldWidgetFactory : WidgetFactory {
    public GoldWidgetFactory(GoldMine goldmine) {
        //...
    }

    public Widget GetWidget() {
        Gold g = goldmine.getGold();
        //...
    }
}

答案 1 :(得分:3)

在这种情况下,我认为使用抽象类而不是接口没有任何好处。

我通常更喜欢接口而不是抽象类:

  • 他们不会在阶级继承中耗尽你的一次机会
  • 他们可以更容易模仿
  • 他们觉得某种程度上“更纯粹”(从界面中可以清楚地了解实施者需要提供的内容;您不需要检查每个方法以查看它是否具体,抽象或虚拟)

但是,在这种情况下,您可以轻松使用委托,因为只有一种方法...基本上是Func<Widget>

我不同意Larry关于使用单个工厂直接使用单独方法创建所有小部件的想法 - 因为您可能希望将WidgetFactory作为依赖项传递给另一个不需要了解的类来源,但需要在不同的时间或可能多次调用CreateWidget

但是,您可以拥有一个小工具工厂,其中包含多个方法,每个方法都返回Func<Widget>。这样可以获得单个工厂类的好处,而允许依赖注入“工厂”概念。

答案 2 :(得分:0)

您不需要继承或接口,甚至不需要多个类。单个工厂应该制作所有不同类型的小部件;您可以将材质作为参数传递给create方法。这个想法是隐藏来自调用者的不同构造对象的方面 - 通过制作一堆你正在暴露它的不同类,而不是隐藏它。

答案 3 :(得分:0)

老实说,除了Concrete Factory类之外,你还希望从WidgetFactory继承吗?什么?......永远? 如果不是,它可能不重要。 如果您希望在它们之间添加公共代码,那么除了抽象类之外,您最好的选择。 此外,我并不认为您的工厂方法需要实现除创建方法之外的任何其他接口。因此无论是抽象还是界面都无关紧要。这一切都归结为将来您是否希望在将来向抽象类添加其他功能。