Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interfaces vs. inheritance: which is better in this case?

Let's suppose I have a widget class:

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

Now, I need to make a factory to create these widgets, so I build a WidgetFactory:

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

As it turns out, you can make widgets out of several different materials, but the resulting widgets are pretty much the same. So, I have a few implementations of 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
    }
}

My question is this: Should WidgetFactory be an abstract class, or an interface? I can see arguments in both directions:

Base class:

  • The implementations ARE WidgetFactories
  • They might be able to share functionality, (say, a List<Widget> WidgetFactory.GetAllWidgets() method)

Interface:

  • The implementations do not inherit any data or functionality from the parent
  • Their internal workings are completely different
  • Only one method is defined

To those answering, this does not (currently) parallel to any real-world problem, but if/when I need to implement this pattern, it would be good to know. Also, "it doesn't matter" is a valid answer.

Edit: I should point out why go through this in the first place. The hypothetical usage of this class hierarchy would be something like:

//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);

So, having a GetGoldWidget() method in WidgetFactory is not a very good idea. Plus, perhaps advents in Widget technology allow us to add different and more exotic types of widgets in the future? It's easier and cleaner to add a new class to handle them than shoehorn a method into an existing class.

like image 490
Mike Caron Avatar asked Feb 26 '23 12:02

Mike Caron


1 Answers

In the example that you have given WidgetFactory has absolutely no reason to be an abstract class since there are not shared attributes or methods between different implementations of the factory.

Even if there was shared functionality, it would be more idiomatic to make an interface and pass it around to the users of WidgetFactory, to reduce the mount of knowledge those components need to have about the factory.

The overall implementation is fine and is really an abstract factory pattern, the only addition I would do is 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();
        //...
    }
}
like image 58
Igor Zevaka Avatar answered Mar 08 '23 22:03

Igor Zevaka