Why Use a Factory Class Instead of Direct Object Construction?

constructorsdesign-patternsfactoryrefactoring

I have seen the history of several ะก# and Java class library projects on GitHub and CodePlex, and I see a trend of switching to factory classes as opposed to direct object instantiation.

Why should I use factory classes extensively? I have pretty good library, where objects are created the old-fashioned way – by invoking public constructors of classes. In the last commits the authors quickly changed all of the public constructors of thousands of classes to internal, and also created one huge factory class with thousands of CreateXXX static methods that just return new objects by calling the internal constructors of the classes. The external project API is broken, well done.

Why would such a change be useful? What is the point of refactoring in this way? What are the benefits of replacing calls to public class constructors with static factory method calls?

When should I use public constructors, and when should I use factories?

Best Answer

Factory classes are often implemented because they allow the project to follow the SOLID principles more closely. In particular, the interface segregation and dependency inversion principles.

Factories and interfaces allow for a lot more long term flexibility. It allows for a more decoupled - and therefore more testable - design. Here is a non-exhaustive list of why you might go down this path:

  • It allows you to introduce an Inversion of Control (IoC) container easily
  • It makes your code more testable as you can mock interfaces
  • It gives you a lot more flexibility when it comes time to change the application (i.e. you can create new implementations without changing the dependent code)

Consider this situation.

Assembly A (-> means depends upon):

Class A -> Class B
Class A -> Class C
Class B -> Class D

I want to move Class B to Assembly B, which is dependent on Assembly A. With these concrete dependencies I have to move most of my entire class hierarchy across. If I use interfaces, I can avoid much of the pain.

Assembly A:

Class A -> Interface IB
Class A -> Interface IC
Class B -> Interface IB
Class C -> Interface IC
Class B -> Interface ID
Class D -> Interface ID

I can now move class B across to assembly B with no pain whatsoever. It still depends on the interfaces in assembly A.

Using an IoC container to resolve your dependencies allows you even more flexibility. There is no need to update each call to the constructor whenever you change the dependencies of the class.

Following the interface segregation principle and the dependency inversion principle allows us to build highly flexible, decoupled applications. Once you have worked on one of these types of applications you will never again want to go back to using the newkeyword.