views:

692

answers:

9

What is your threshold to use factory instead of a constructor to create an object?

  1. You always use factory.
  2. You use factories only if you have invariant checks other than checking for nulls.
  3. You always use constructors
  4. You rarely use factories... what are those cases??

pros and cons

Update: I am applying factory pattern from Domain Driven Design in my project. And one of the reason behind creating factories is to reduce noise in the domain model.

Thanks

+1  A: 

I like to keep the number of constructors to a reasonable low level; more than two or three, and I question how well the object's construction is designed.

In cases where additional constructors are being introduced to support setting various optional attributes, I like to use a Builder, as described in Effective Java (Joshua Bloch, 2nd ed.)

Rob
A: 

I try to measure between those. I think that you should use factories when:

  1. High number of param.
  2. Optional param. (Both using the inner class Builder pattern)
  3. You will have to change the order of parameters in order to acomplish other action, due to same parameter types but diferent data.
  4. You need a singleton class (better done with enum)

With factories, in this case, you can give a proper name to the object state being returned.

José Leal
+2  A: 

I not exactly sure how you chose your thresholds...

Factories are appropriate if you don't want to abstract the consumer of the object from the construction. Instances where this may be pertinent:

  • You may want to sub out the implementation at runtime. Often this is combined with using interfaces rather than concrete classes. An example in Java would be how you get a Document object from a DocumentBuilder in Java.
  • You may want to limit the # of instances of an object. Think of constructing a Pool with a limited number of thread objects rather than just creating new all the time

Check out the Book of Four (Gamma et. al.) patterns book and look at the factory pattern in detail for more information about when to use this pattern.

Rob Di Marco
+10  A: 

I use a factory if I have an abstract base class (or an interface), and several concrete derived classes, and there is some logic according to which one of concrete classes is created. I implement that logic in the factory.

Igor Oks
The point of a factory is to separate object creation from the client, and as such, there is nothing wrong with a 1:1 ratio between concrete classes and the abstract classes in a factory pattern.
alord1689
+5  A: 

The most obvious case for a factory is when the specific class implementing an interface will be chosen at runtime, for example, from a configuration file. I don't make heavy use of factories, but when I want two objects to be highly decoupled, I am more likely to use a factory for one to get an instance of the other.

Eddie
A: 

Use a factory when the decision of which concrete class to instantiate is not up to the client. e.g. where there are several 'families' of objects and the choice of which family to use is made elsewhere.

Noel Walters
+2  A: 

Something interesting about C# that relates to this topic, is that the new() constraint on generic types that are specified in a class definition forces the types that are handled by the generic container type to implement a parameterless constructor. The new() constraint is only needed when one intends to create an instance of type T, as in GenericType<T>, within the class. It seems to me that this is explicitly in support of class factories, especially factories which produce generic types.

To turn this requirement on its head, the Windows Communication Foundation (WCF) has a ChannelFactory class that defines the following static factory method:

public static TChannel CreateChannel(Binding binding, EndpointAddress endpointAddress, Uri via)
{
    ChannelFactory<TChannel> factory = new ChannelFactory<TChannel>(binding);
    if (factory.HasDuplexOperations())
    {
        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString("SFxInvalidStaticOverloadCalledForDuplexChannelFactory1", new object[] { factory.channelType.Name })));
    }
    TChannel channel = factory.CreateChannel(endpointAddress, via);
    ChannelFactory<TChannel>.SetFactoryToAutoClose(channel);
    return channel;
}

If you look in Reflector at the class disassembly (System.ServiceModel assembly & System.ServiceModel.Channels namespace), you'll notice that "new()" is not used as a constraint.

That's because the CreateChannel method uses typeof(TChannel) to delegate the object creation further down the chain...

public virtual TChannel CreateChannel(EndpointAddress address, Uri via)
{
    TChannel local;
    bool traceOpenAndClose = base.TraceOpenAndClose;
    try
    {
        using (ServiceModelActivity activity = (DiagnosticUtility.ShouldUseActivity && base.TraceOpenAndClose) ? ServiceModelActivity.CreateBoundedActivity() : null)
        {
            if (DiagnosticUtility.ShouldUseActivity)
            {
                ServiceModelActivity.Start(activity, this.OpenActivityName, this.OpenActivityType);
                base.TraceOpenAndClose = false;
            }
            if (address == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
            }
            if (base.HasDuplexOperations())
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString("SFxCreateNonDuplexChannel1", new object[] { base.Endpoint.Contract.Name })));
            }
            base.EnsureOpened();
            local = (TChannel) this.ServiceChannelFactory.CreateChannel(typeof(TChannel), address, via);
        }
    }
    finally
    {
        base.TraceOpenAndClose = traceOpenAndClose;
    }
    return local;
}

You can follow the delegation chain several more levels deep as the Type class is being passed down until the following method is finally called:

RemotingServices.CreateTransparentProxy(this, classToProxy, stub, stubData);

It is extremely convoluted, but it's the most complicated factory I have ever seen. Interestingly enough, all of the machinations end up with WCF creating a RealProxy class from the System.Runtime.Remoting.Proxies namespace.

In conclusion, factories are for objects that have a lot of complexity or need to benefit from dynamic type construction.

EnocNRoll
A: 

I think you are confusing the Builder pattern and the Factory pattern. I would suggest just using constructors and being done with it. It sounds like (without seeing the code) you're overthinking or overanalysing your code a bit.

Travis
A: 

Here's a radical thought (I'm not really advocating it, but I don't think it would harm):

Always use factory methods!

Factory methods are more flexible, e.g., they can cache results or return child classes.

So, instead of:

class SomeClass {
  public SomeClass(/*parameters*/) { /*...*/ }
}

Always use:

class SomeClass {
  protected SomeClass(/*parameters*/) { /*...*/ }
  public static SomeClass New(/*parameters*/) {
    return new SomeClass(/*parameters*/);
  }
}

The caller code changes from:

SomeClass sc = new SomeClass();

To:

SomeClass sc = SomeClass.New();

You can now change your "constructor" logic to return sub-classes or cached instances, and all your callers are not affected. You now control the return value of your "constructors".

Jordão