views:

101

answers:

4

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.

A: 

You don't need inheritance or an interface or even more than one class. The single factory should make all different kinds of widgets ; you can just pass in the materials as a parameter to the create method. The idea is to hide the aspects of different construction of objects from the caller - by making a bunch of different classes you are exposing this, not hiding it.

Larry Watanabe
I've added a note to my question clarifying why this is not a very good answer
Mike Caron
+3  A: 

In this case I see no benefit to using an abstract class instead of an interface.

I would generally favour interfaces over abstract classes:

  • They don't use up your one opportunity at class inheritance
  • They can be easier to mock
  • They feel "purer" somehow (it's clear just from the interface what the implementer needs to provide; you don't need to check each method to see whether or not it's concrete, abstract, or virtual)

In this case, however, you could easily use a delegate as there's only a single method... basically a Func<Widget>.

I disagree with Larry's idea of just using a single factory to directly create all the widgets with separate methods - as you may want to pass the WidgetFactory as a dependency to another class which doesn't need to know about the source, but needs to call CreateWidget either at a different time or possibly multiple times.

However, you could have a single widget factory with multiple methods each returning a Func<Widget>. That would give the benefits of having a single factory class while also allowing for dependency injection of the "factory" notion.

Jon Skeet
So, essentially, a `WidgetFactoryFactory`? Hmm, that's an interesting way to think about it. I'm not too good with closures, though, so I'd tend toward discrete implementations of the factories...
Mike Caron
Hmmm.... A lambda factory. It might be a good fit for a particular factory problem I had a while back...
Igor Zevaka
you don't need a different method name -- you can use the same method, and overide the method with different methods for different input types, e.g. GetWidget(Goldmine m), GetWidget(Bronze b), etc.
Larry Watanabe
+5  A: 

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();
        //...
    }
}
Igor Zevaka
I think your first sentence is the wrong way round - there's no reason to be an *abstract class*.
Jon Skeet
Indeed, thank you very much.
Igor Zevaka
So, just to clarify, where would my hypothetical `GetAllWidgets()` method fit in (which I would probably implement by calling GetWidget() until there aren't any more, using a `WidgetAvailable` property I just invented)?
Mike Caron
The only difference is I would make IWidgetFactory a generic and constrain it to a Widget, so that GetWidget would be properly typed.
Tom Anderson
`GetAllWidgets` doesn't really belong on the widget factory. It's actually a component on its own. Something like `WidgetFactoryCollection` class with `GetAllFactories` method - essentially providing you with a list of factories you can use.
Igor Zevaka
@Tom Anderson. It doesn't really make sense to constrain the base factory interface since you really want to get a widget using the same method out of different factories.
Igor Zevaka
I can see your point if the Widget it's self is properly abstracted.
Tom Anderson
A: 

Honestly, what ever else, besides the Concrete Factory classes, do you expect to inherit from WidgetFactory? Anything?... ever? If not it probably doesn't ever matter. If down the road you want to add common code between them all than an abstract class would be your best bet. Also I don't really see the need for your factory methods to implement any other interface except that of your creation method. So it doesn't matter whether it's abstract or interface. It all comes down to whether in the future you will want to add additional functionality in the future to the abstract class.

C Johnson