Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 586
StackUnderflow Avatar asked Jan 28 '09 22:01

StackUnderflow


People also ask

Why would one use the factory method rather than just using a constructor?

A factory method can return an already created object, unlike a constructor, which always creates a new instance.

When should you use Factory Pattern?

The factory design pattern is used when we have a superclass with multiple sub-classes and based on input, we need to return one of the sub-class. This pattern takes out the responsibility of the instantiation of a class from the client program to the factory class.

What is the benefit of using a factory class rather than just creating an object directly with new?

Factory Method requires subclassing, but doesn't require Initialize. The advantage of a Factory Method is that it can return the same instance multiple times, or can return a subclass rather than an object of that exact type.

Can constructors be used to create an object?

Simply speaking, a constructor does not create an object. It just initializes the state of the object. It's the new operator which creates the object.


3 Answers

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.

like image 110
Igor Avatar answered Nov 16 '22 04:11

Igor


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.

like image 24
Eddie Avatar answered Nov 16 '22 03:11

Eddie


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.

like image 42
EnocNRoll - AnandaGopal Pardue Avatar answered Nov 16 '22 03:11

EnocNRoll - AnandaGopal Pardue