195

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?

guo
  • 103
rufanov
  • 2,003

9 Answers9

159

Like whatsisname said, I believe this is case of cargo cult software design. Factories, especially the abstract kind, are only usable when your module creates multiple instances of a class and you want to give user of this module ability to specify what type to create. This requirement is actually quite rare, because most of the time you just need one instance and you can just pass that instance directly instead of creating an explicit factory.

The thing is, factories (and singletons) are extremely easy to implement and so people use them a lot, even in places where they are not necessary. So when programmer thinks "What design patterns should I use in this code?" the Factory is first that comes to his mind.

Many factories are created because "Maybe, one day, I will need to create those classes differently" in mind. Which is a clear violation of YAGNI.

And factories become obsolete when you introduce IoC framework, because IoC is just a kind of factory. And many IoC frameworks are able to create implementations of specific factories.

Also, there is no design pattern that says to create huge static classes with CreateXXX methods which only call constructors. And it is especially not called a Factory (nor Abstract Factory).

Robert Harvey
  • 200,592
Euphoric
  • 38,149
98

The Factory pattern vogue stems from an almost-dogmatic belief among coders in "C-style" languages (C/C++, C#, Java) that use of the "new" keyword is bad, and should be avoided at all costs (or at least centralized). This, in turn, comes from an ultra-strict interpretation of the Single Responsibility Principle (the "S" of SOLID), and also of the Dependency Inversion Principle (the "D"). Simply stated, the SRP says that ideally a code object should have one "reason to change", and one only; that "reason to change" is the central purpose of that object, its "responsibility" in the codebase, and anything else that requires a change to code should not require opening up that class file. The DIP is even simpler; a code object should never be dependent upon another concrete object, but instead on an abstraction.

Case in point, by using "new" and a public constructor, you are coupling the calling code to a specific construction method of a specific concrete class. Your code now has to know that a class MyFooObject exists, and has a constructor that takes a string and an int. If that constructor ever needs more information, all usages of the constructor have to be updated to pass in that information including the one you're writing now, and therefore they are required to have something valid to pass in, and so they must either have it or be changed to get it (adding more responsibilities to the consuming objects). In addition, if MyFooObject is ever replaced in the codebase by BetterFooObject, all usages of the old class have to change to construct the new object instead of the old one.

So, instead, all consumers of MyFooObject should be directly dependent on "IFooObject", which defines the behavior of implementing classes including MyFooObject. Now, consumers of IFooObjects can't just construct an IFooObject (without having the knowledge that a particular concrete class is an IFooObject, which they don't need), so instead they must be given an instance of an IFooObject-implementing class or method from outside, by another object that has the responsibility of knowing how to create the correct IFooObject for the circumstance, which in our parlance is usually known as a Factory.

Now, here's where theory meets reality; an object can never be closed to all types of change all the time. Case in point, IFooObject is now an additional code object in the codebase, which must change whenever the interface required by consumers or implementations of IFooObjects change. That introduces a new level of complexity involved in changing the way objects interact with each other across this abstraction. In addition, consumers will still have to change, and more deeply, if the interface itself is replaced by a new one.

A good coder knows how to balance YAGNI ("You Ain't Gonna Need It") with SOLID, by analyzing the design and finding places that are very likely to have to change in a particular way, and refactoring them to be more tolerant of that type of change, because in that case "you are gonna need it".

KeithS
  • 22,282
74

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.

Stephen
  • 8,868
  • 3
  • 31
  • 43
36

Constructors are fine when they contain short, simple code.

When initialization becomes more than assigning a few variables to the fields, a factory makes sense. Here are some of the benefits:

  • Long, complicated code makes more sense in a dedicated class (a factory). If the same code is put in a constructor which calls a bunch of static methods, this will pollute the main class.

  • In some languages and some cases, throwing exceptions in constructors is a really bad idea, since it can introduce bugs.

  • When you invoke a constructor, you, the caller, needs to know the exact type of the instance you want to create. This is not always the case (as a Feeder, I just need to construct the Animal in order to feed it; I don't care if it's a Dog or a Cat).

13

If you work with interfaces then you can remain independent of the actual implementation. A factory can be configured (via properties, parameters or some other method) to instantiate one of a number of different implementations.

One simple example: you want to communicate with a device but you don't know if it will be via Ethernet, COM or USB. You define one interface and 3 implementations. At runtime you could then select which method you want and the factory will give you the appropriate implementation.

Use it often...

paul
  • 1,191
9

It's a symptom of a limitation in Java/C#'s module systems.

In principle, there's no reason you shouldn't be able to swap out one implementation of a class for another with the same constructor and method signatures. There are languages that allow this. However, Java and C# insist that every class have a unique identifier (the fully qualified name) and the client code ends up with a hard-coded dependency on it.

You can sort of get around this by fiddling with the file system and compiler options so that com.example.Foo maps to a different file, but this is surprising and unintuitive. Even if you do so, your code is still tied to only one implementation of the class. I.e. If you write a class Foo that depends on a class MySet, you can choose an implementation of MySet at compile time but you still can't instantiate Foos using two different implementations of MySet.

This unfortunate design decision forces people to use interfaces unnecessarily to future-proof their code against the possibility that they'll later need a different implementation of something, or to facilitate unit testing. This isn't always feasible; if you have any methods that look at the private fields of two instances of the class, won't be able to implement them in an interface. That's why, for example, you don't see union in Java's Set interface. Still, outside of numeric types and collections, binary methods aren't common, so you can usually get away with it.

Of course, if you call new Foo(...) you still have a dependency on the class, so you need a factory if you want a class to be able to instantiate an interface directly. However, it's usually a better idea to accept the instance in the constructor and let someone else decide which implementation to use.

It's up to you to decide if it's worth bloating your codebase with interfaces and factories. On the one hand, if the class in question is internal to your codebase, refactoring the code so that it uses a different class or an interface in the future is trivial; you could invoke YAGNI and refactor later if the situation arises. But if the class is part of the public API of a library you've published, you don't have the option of fixing the client code. If you don't use an interface and later need multiple implementations, you'll be stuck between a rock and a hard place.

Doval
  • 15,487
3

In my opinion, they're just using the Simple Factory, which is not a proper design pattern and should not be confused with the Abstract Factory or the Factory Method.

And since they have created a "huge fabric class with thousands of CreateXXX static methods", that sounds to an anti-pattern (a God class maybe?).

I think the Simple Factory and static creator methods (which doesn't require an external class), can be useful in some cases. For example, when the construction of an object requires various steps like instancing other objects (e.g. favoring composition).

I wouldn't call even call that a Factory, but just a bunch of methods encapsulated in some random class with the suffix "Factory".

FranMowinckel
  • 225
  • 1
  • 5
1

As the user of a library, if the library has factory methods, then you should use them. You would assume that the factory method gives the author of the library the flexibility to make certain changes without affecting your code. They might for example return an instance of some subclass in a factory method, which wouldn't work with a simple constructor.

As the creator of a library, you would use factory methods if you want to use that flexibility yourself.

In the case you describe, you seem to have the impression that replacing the constructors with factory methods was just pointless. It was certainly a pain for everyone involved; a library shouldn't remove anything from its API without a very good reason. So if I had added factory methods, I would have left existing constructors available, perhaps deprecated, until a factory method doesn't just call that constructor anymore and code using the plain constructor works less good than it should. Your impression might very well be right.

gnasher729
  • 49,096
-4

This seems to be obsolete in the age of Scala and functional programming. A solid foundation of functions replaces a gazillion classes.

Also to note that Java's double {{ doesn't work anymore when using a factory i.e

someFunction(new someObject() {{
    setSomeParam(...);
    etc..
}})

Which can let you create an anonymous class and customize it.

In the time space dilema the time factor is now so much shrunk thanks to fast CPUs that functional programming enabling the shrinking of space i.e code size is now practical.

Robert Harvey
  • 200,592
Marc
  • 1