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.

I was writing some code over the weekend and I found myself wanting to write a factory as a static method in a base class.

My question is simply to know if this is a c# idomatic approach?

My sense that it might not be comes from the fact that the base class has knowledge of the derived class.

That said, I'm not sure of a simpler way to get the same result. A whole other factory class seems (to me at least) like unneeded complexity (?)

Something like:

class Animal
{
  public static Animal CreateAnimal(string name)
  {
     switch(name)
     {
        case "Shark":
          return new SeaAnimal();
          break;
        case "Dog":
          return new LandAnimal();
          break;
        default:
          throw new Exception("unknown animal");
     }
  }
}
class LandAnimal : Animal
{
}

class SeaAnimal : Animal
{
}
share|improve this question
    
How will you test your factories? –  user1249 Mar 5 '12 at 17:27
    
with the code in this question, i would not. but the answer has helped inch me along the path of integrating more testing into my coding style –  Aaron Anodide Mar 5 '12 at 17:29
    
Consider that having pulled in both the Seaworld and the Landworld in your Animal class, all in all make it harder to handle in an isolated setting. –  user1249 Mar 5 '12 at 17:31
add comment

3 Answers

up vote 12 down vote accepted

Well, the advantage of a separate factory class is that it can be mocked out in unit tests.

But if you're not going to do that, or make it polymorphic in any other way, then a static Factory method on the class itself is OK.

share|improve this answer
    
thanks, could you give an example of what you are referring to when you say polymorphic any other way? –  Aaron Anodide Mar 5 '12 at 16:34
    
I mean that if you ever want to be able to replace one factory method with another. Mocking it for test purposes is just one of the most common examples of that. –  pdr Mar 5 '12 at 17:06
add comment

You could use Generics to avoid the switch statement and decouple the downstream implementations from the base class as well.:

 public static T CreateAnimal<T>() where T: new, Animal
 {
    return new T();
 }

Usage:

LandAnimal rabbit = Animal.CreateAnimal();  //Type inference should should just figure out the T by the return indicated.

or

 var rabbit = Animal.CreateAnimal<LandAnimal>(); 
share|improve this answer
    
interesting altertantive, thanks –  Aaron Anodide Mar 5 '12 at 16:46
2  
2  
@PeterK. Fowler refers to switch statements in Code Smells, but his solution is that they should be extracted to Factory classes, rather than being replaced. That said, if you are always going to know the type at development time, generics is an even better solution. But if you don't (as the original example implied) then I would argue that using reflection to avoid a switch in a factory method can be a false economy. –  pdr Mar 5 '12 at 17:10
    
switch statements and if-else-if chains are the same. i use the former because of the compile time checking that forces the default case to be handled –  Aaron Anodide Mar 5 '12 at 17:24
4  
@PeterK, in a switch statement the code is in a single place. In full-blown OO the same code may be spread over multiple, separate classes. There is a grey area where the added complexity of having numerous snippets is less desirable than a switch-statement. –  user1249 Mar 5 '12 at 17:29
show 10 more comments

Taken to the extreme, the factory could be generic as well.

interface IFactory<K, T> where K : IComparable
{
    T Create(K key);
}

Then one can create any type of factory of objects, which in turn could create any type of object. I am not sure if that is simpler, it is certainly more generic.

I don't see anything wrong with a switch statement for a small factory implementation. Once you are into large number of objects or possible different class hierarchies of objects, I think a more generic approach is better suited.

share|improve this answer
    
thanks for the insights –  Aaron Anodide Mar 5 '12 at 20:06
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.