What is your threshold to use factory instead of a constructor to create an object?
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
A factory method can return an already created object, unlike a constructor, which always creates a new instance.
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With