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

Mik*_*ron 4 c# inheritance interface

假设我有一个widget类:

struct Widget {
    public Color Color { get; set; }
    public int Frobbles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

abstract class WidgetFactory {
    public virtual Widget GetWidget();
}
Run Code Online (Sandbox Code Playgroud)

事实证明,你可以用几种不同的材料制作小部件,但结果小部件几乎是一样的.所以,我有一些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
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是: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);
Run Code Online (Sandbox Code Playgroud)

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

Igo*_*aka 5

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

即使存在共享功能,制作接口并将其传递给用户也会更加惯用WidgetFactory,以减少这些组件对工厂所需的知识.

整体实现很好,实际上是一个抽象的工厂模式,我唯一要做的就是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();
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)