代码之家  ›  专栏  ›  技术社区  ›  Mike Caron

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

  •  4
  • Mike Caron  · 技术社区  · 14 年前

    假设我有一个widget类:

    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
        }
    }
    

    基类:

    • 实现是widgetfactures
    • 他们也许能够共享功能,(比如说 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);
    

    GetGoldWidget() WidgetFactory中的方法不是一个好主意。另外,也许在小部件技术上的冒险让我们在未来添加不同的和更奇特的小部件类型?添加一个新类来处理它们比将一个方法硬塞进一个现有的类更简单、更干净。

    4 回复  |  直到 13 年前
        1
  •  0
  •   C.J.    14 年前

    老实说,除了具体的工厂类之外,您还希望从WidgetFactory继承什么?有什么事吗?。。。有过吗? 如果您想在它们之间添加公共代码,那么最好使用抽象类。 此外,我并不认为工厂方法需要实现除创建方法之外的任何其他接口。所以不管它是抽象的还是接口的。归根结底,将来您是否希望在抽象类中添加额外的功能。

        2
  •  5
  •   Igor Zevaka    14 年前

    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();
            //...
        }
    }
    
        3
  •  3
  •   Jon Skeet    14 年前

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

    • 他们不会浪费你继承类的机会
    • 他们更容易被嘲笑

    不过,在这种情况下,您可以很容易地使用委托,因为只有一个方法。。。基本上是 Func<Widget> .

    我不同意Larry的想法,只使用一个工厂直接用不同的方法创建所有的小部件,因为您可能想通过 WidgetFactory 作为对另一个类的依赖,该类不需要知道源代码,但需要调用 CreateWidget 在不同的时间或者可能多次。

    能够 有一个具有多个方法的小部件工厂,每个方法返回一个 . 这将给一个单一的工厂阶级的好处 允许“工厂”概念的依赖注入。

        4
  •  0
  •   Larry Watanabe    14 年前

    您不需要继承或接口,甚至不需要多个类。单个工厂应该生产各种各样的小部件;只需将材质作为参数传递给create方法。这样做的目的是对调用者隐藏对象的不同构造的各个方面—通过创建一组不同的类,您可以公开这些内容,而不是隐藏这些内容。