Factory Design pattern and keyword 'new'
Consider in your client / caller class you write:
Vehicle v = new Car("BMW");
If your code is like the one above, you will always get a Car. In the future if you actually want a Plane, you will have to update the client code.
Alternatively, you use a factory pattern, you code something like:
Vehicle v = Factory.getVehicle();
Now you can keep the logic of getting the vehicle away (loose coupling) from the client and your client would never need a change in case you have to update the end vehicle you get. Only the Factory implementation will update and your clients will work as is.
I wouldn't go so far to say that new
is considered harmful. What the abstract factory pattern attempts to do is solve the problem that new
is not overrideable (i.e. is not compatible with virtual dispatch, at least in languages like Java and C#).
Consider this sample code (C#):
class Sender
{
private ISendChannel channel;
public Sender()
{
}
public void Connect(Uri endpointAddress)
{
// !! Sender is tightly coupled to TCP implementation
// !! even though it doesn't apparently have to be.
this.channel = new TcpSendChannel(endpointAddress);
}
/* ... */
}
In this code, we have a base interface ISendChannel
to allow forward communication to some endpoint. However, the implementation as given is fixed to always use a TCP channel no matter what. This is not desirable because now if you want an HTTP sender, you either have to modify the Sender
class or add new methods to it. This is "bad coupling".
Instead, you could use a factory to create channels and pass it in to the sender. The sender will ask the factory to create the channel and thus give up that responsibility. The new implementation may look like this:
class Sender
{
private readonly ISendChannelFactory factory;
private ISendChannel channel;
public Sender(ISendChannelFactory factory)
{
this.factory = factory;
}
public void Connect(Uri endpointAddress)
{
// Sender does not have to care what type of channel it is.
this.channel = this.factory.CreateSendChannel(endpointAddress);
}
/* ... */
}
Now to use an HTTP channel, you could instantiate a sender using a different factory type, e.g. new Sender(new HttpSendChannelFactory(/* ... */));
. The HttpSendChannelFactory
could then return HttpSendChannel
(a concrete type deriving from ISendChannel
) from its CreateSendChannel
method.
I suggest reading this article: http://www.codinghorror.com/blog/2005/09/head-first-design-patterns.html
key part is: The best way to learn to write simple code is to write simple code! Patterns, like all forms of complexity, should be avoided until they are absolutely necessary. That's the first thing beginners need to learn. Not the last thing.
I agree with it - you need factory only when you really need it.
Ok, going back to topic, keyword new
can be evil, but in most of cases it surely isn't and shouldn't be source of headache. Seeing
List <Person> persons = new ArrayList<Person>();
Is perfectly fine. Don't even dare to think about factory producing ArrayList
or LinkedList
. That would be totally overengineered.
"I’ve seen numerous systems in which the Factory pattern was overused. For example, if every object in a system is created by using a Factory, instead of direct instantiation (e.g., new StringNode(ノ)),the system probably has an overabundance of Factories." @ Joshua Kerievsky
Don't add patterns premature unless you're sure that it's good idea, and you can't be sure of that without enough experience. Starting writing code with patterns in your mind - kind of: Factory, this is great, lets see when I can place it! - that's not a good idea :). Better would be adding patterns to places in your code that are troublesome, when you feel (smell :) - code smell) that this could be done somehow better. That is refactoring to patterns.
There is a great book about it, and I'll give you link to chapter "Move Creation Knowledge to Factory"
http://www.informit.com/articles/article.aspx?p=1398606&seqNum=2
I know it's long, but read it please, it's surely worth the effort