Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

From the "Gang of Four" design patterns, there's the Factory method:

class Factory(product)
  case product
  when a
    new A
  when b
    new B
  when c
    new C
end

new Factory(a)

Why is this more useful than having three classes, a, b, and c and calling them individually?

share|improve this question
    
What do you mean precisely? Why not instantiate all three? Is that what you mean? –  Neil Jun 6 '13 at 7:57
    
@Neil No, in the factory pattern all the classes exist as siblings. Why call the factory to indirectly access the a,b,c classes? –  Jackson Gariety Jun 6 '13 at 7:58
1  
this doesn't actually look like the factory method pattern to me, if anything its closer to abstract factory –  jk. Jun 6 '13 at 8:02
1  
Because at design time you don't know which of the 3 classes you need to instantiate. –  w3d Jun 6 '13 at 8:02
1  
@jk: No, it really doesn't. programmers.stackexchange.com/questions/81838/… –  pdr Jun 6 '13 at 10:28
show 1 more comment

4 Answers

up vote 10 down vote accepted

Because your example is not complicated enough. For such a simple scenario it doesn't even make sense to use an advanced pattern.

But if you have to know more than the product to construct A, B or C, and you can't have direct access to that knowledge, then it is useful. Then you are using the factory to act as a knowledge center for producing needed objects.

Maybe those objects need a reference to some object X, which the factory can provide, but your code in the place where you want to construct A, B or C can't or shouldn't have access to X. Maybe when you have X you create A and B but if you have Y type then you create C.

Also consider that some objects might need 20 dependencies to create; what then? Going to hunt for those dependencies in a place where they should not be accessible might be problematic.

share|improve this answer
    
+1 for making it clear that Factory pattern is not always the best approach. –  Neil Jun 6 '13 at 8:33
    
Because your example is not complicated enough. For such a simple scenario it doesn't even make sense to use an advanced pattern. So what would you do in this case? Inline the conditional construction? –  pdr Jun 6 '13 at 10:31
    
It can be just method that takes product and returns what you need to make it reusable, so it doesn't have to be inline. If such method grows into something bigger, or is used in several other classes, you can refactor it to different class. –  Mateusz Jun 6 '13 at 11:34
    
The pattern is called Factory Method for a reason. The method doesn't have to be in a different class to be a Factory Method (though it often is). –  pdr Jun 6 '13 at 11:46
    
I've missed the "Method" in it, so you are right mister. –  Mateusz Jun 6 '13 at 11:54
add comment

The key advantages of the Factory pattern are twofold:

  1. The places that need an implementation of the product do not need to know how to construct one. The factory holds that information.

    Do you want to know what arguments to pass to the particular constructor? Or what dependencies you have to inject? Or how to register the implementation class with the database after it is fully configured? No? Let the factory look after all that stuff.

  2. The places that need an implementation of the product do not need to know at the time of module description (i.e., at compilation time) what the name of the implementation class is.

    Thus, a need not have anything to do with A; the “what to build” can be described in terms of the desired non-functional properties, and not just the name. This is much more flexible.

The downside is that where you know what to make and how to do it, you get more complexity when you use a factory. The fix to that is simple though: don't use a factory when it doesn't make sense!

share|improve this answer
add comment

A factory pattern is usually more complex than that. A factory decides on certain criteria which instance to create/return. Instead, when you don't use the factory, you would have that code repeatedly used in several locations in your code.

As an example consider the following: you need to load data from a DB, but you have one central DB for integration with lots of data, and one smaller one in memory on each dev-PC. In your code you ask a factory to get a DB-handle and the factory returns one of those depending on e.g. a configuration file.

share|improve this answer
add comment

The Factory Method pattern abstracts the decision-making process from the calling class. This has several advantages:

Reuse. If I want to instantiate in many places, I don't have to repeat my condition, so when I come to add a new class, I don't run the risk of missing one.

Unit-Testability. I can write 3 tests for the factory, to make sure it returns the correct types on the correct conditions, then my calling class only needs to be tested to see if it calls the factory and then the required methods on the returned class. It needs to know nothing about the implementation of the factory itself or the concrete classes.

Extensibility. When someone decides we need to add a new class D to this factory, none of the calling code, neither unit tests or implementation, ever needs to be told. We simply create a new class D and extend our factory method. This is the very definition of Open-Closed Principle.

You can even create a new factory class and make them hot-swappable, if the situation requires it -- for example, if you want to be able to switch class D on and off, while testing. I have run into this situation only once, but it was extremely useful.

As has been said, the Factory Pattern isn't always the way to go. But, wherever you see conditional instantiation, you should give it a moment's thought.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.