191

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?

5

9 Answers 9

72

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.

19
  • 51
    IMO factories are least important thing for SOLID. You can do SOLID just fine without factories.
    – Euphoric
    Commented Aug 14, 2014 at 6:29
  • 33
    One thing that never made sense to me is, if you use factories to make new objects then you have to make the factory in the first place. So what exactly does that get you? Is it assumed that someone else will give you the factory instead of you instantiating it on your own, or something else? This should be mentioned in the answer, otherwise it's unclear how factories actually solve any problem.
    – user541686
    Commented Aug 14, 2014 at 10:14
  • 10
    @BЈовић - Except that every time you add a new implementation, you now get to crack open the factory and modify it to account for the new implementation - explicitly violating OCP.
    – Telastyn
    Commented Aug 14, 2014 at 12:58
  • 7
    @Telastyn Yes, but the code using the created objects do not change. That is more important then the changes to the factory. Commented Aug 14, 2014 at 13:34
  • 9
    Factories are useful in certain areas which the answer addressed. They are not appropriate to use everywhere. For example, using factories to create strings or lists would be taking it way too far. Even for UDTs they are not always necessary. The key is to use a factory when the exact implementation of an interface needs to be decoupled.
    – user22815
    Commented Aug 14, 2014 at 14:43
157

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).

16
  • 7
    I agree with most of your points except "IoC is kind of factory": IoC containers are not factories. They are a convenient method of achieving dependency injection. Yes, some are capable of constructing automatic factories, but they are not factories themselves and should not be treated as such. I'd also contend the YAGNI point. It is useful to be able to substitute a test double in your unit test. Refactoring everything to provide this after the fact is a pain in the ass. Plan ahead and don't fall for the "YAGNI" excuse
    – Alex
    Commented Aug 14, 2014 at 11:29
  • 14
    @AlexG - eh... in practice, pretty much all IoC containers work as factories.
    – Telastyn
    Commented Aug 14, 2014 at 12:59
  • 8
    @AlexG Primary focus of IoC is to construct concrete objects for passing into other objects based on configuration/convention. This is same thing as using factory. And you don't need factory to be able to create a mock for test. You just instantiate and pass the mock directly. Like I said in first paragraph. Factories are only useful when you want to pass creation of an instance to user of the module, which calls the factory.
    – Euphoric
    Commented Aug 14, 2014 at 13:41
  • 5
    There's a distinction to be made. The factory pattern is used by a consumer to create entities during the runtime of a program. An IoC container is used to create the object graph of the program during start-up. You can do this by hand, the container is just a convenience. The consumer of a factory should not be aware of the IoC container.
    – Alex
    Commented Aug 14, 2014 at 14:16
  • 5
    Re: "And you don't need factory to be able to create a mock for test. You just instantiate and pass the mock directly" - again, different circumstances. You use a factory to request an instance - the consumer is in control of this interaction. Supplying an instance through the constructor or a method doesn't work, it's a different scenario.
    – Alex
    Commented Aug 14, 2014 at 14:26
97

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".

8
  • 28
    Love this answer, in special after reading all other ones. I can add almost all (good) new coders are too much dogmatic about principles by the simple fact they really want to be good but don't learned yet the value of keeping things simple and don't overkill.
    – jean
    Commented Aug 14, 2014 at 17:48
  • 1
    Another problem with public constructors is that there's no nice way for a class Foo to specify a public constructor should be usable for the creation of Foo instances, or the creation of other types within the same package/assembly, but should not be usable for the creation of types derived elsewhere. I don't know of any particularly compelling reason a language/framework couldn't define separate constructors for use in new expressions, versus invocation from subtype constructors, but I don't know of any languages that do make that distinction.
    – supercat
    Commented Feb 11, 2015 at 16:12
  • 2
    A protected and/or internal constructor would be such a signal; this constructor would only be available to consuming code whether in a subclass or within the same assembly. C# does not have a keyword combination for "protected and internal" meaning only subtypes within the assembly could use it, but MSIL has a scope identifier for that type of visibility so it's conceivable the C# spec could be extended to provide a way to utilize it. But, this really doesn't have much to do with the use of factories (unless you use the restriction of visibility to enforce a factory's use).
    – KeithS
    Commented May 4, 2015 at 15:52
  • 3
    Perfect answer. Right on point with the 'theory meets reality' part. Just think of how many thousands of developers and human time spent cargo-cult praising, justifying, implementing, using them to then falling to the same situation you described, is just maddening. Following YAGNI, Ive never identified the need to implement a factory Commented Dec 9, 2017 at 1:54
  • 1
    Nice answer, but I have one disagreement, new being evil is more of C++ thing. for C#/Java new is perfectly alright with most programmers. Commented Jun 4, 2020 at 11: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).

5
  • 2
    The choices are not only "factory" or "constructor." A Feeder might use neither, and instead call it's Kennel object's getHungryAnimal method.
    – DougM
    Commented Aug 14, 2014 at 13:13
  • 6
    +1 I find that adhering to a rule of absolutely no logic in a constructor is not a bad idea. A constructor should only be used for setting the initial state of the object by assigning its arguments values to instance variables. If anything more complicated is needed, at the very least make a factory (class) method to build the instance. Commented Aug 14, 2014 at 15:07
  • This is the only satisfying answer I've seen here, saved me from having to write my own. The other answers are only dealing in abstract concepts. Commented Mar 17, 2017 at 18:15
  • But this argument can be held valid true for Builder Pattern as well. Isn't it ?
    – soufrk
    Commented Sep 26, 2017 at 14:07
  • Constructors rule Commented Dec 9, 2017 at 1:58
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...

2
  • 7
    I would add that it is great to use when there are multiple implementations of an interface and the calling code does not or should not know which one to pick. But when a factory method is simply a static wrapper around a single constructor as in the question, that is the anti-pattern. There has to be multiple implementations from which to pick or the factory is getting in the way and adding unnecessary complexity.
    – user22815
    Commented Aug 14, 2014 at 14:46
  • Now you have the added flexibility and in theory your application can use Ethernet, COM, USB and serial, is ready for fireloop or whatever, in theory. In reality your app will only communicate over Ethernet....ever.
    – Pieter B
    Commented Feb 1, 2016 at 12:11
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.

1
  • 2
    I wish Java and derivatives like .NET had a special syntax for a class creating instances of itself, and otherwise had new simply be syntactic sugar for calling a specially-named static method (which would be auto-generated if a type had a "public constructor" but didn't explicitly include the method). IMHO, if code just wants a boring default thing that implements List, it should be possible for the interface to give it one without the client having to know of any particular implementation (e.g. ArrayList).
    – supercat
    Commented Aug 14, 2014 at 20:39
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".

5
  • 1
    Simple Factory has its place. Imagine an entity takes two constructor parameters, int x and IFooService fooService. You don't want to be passing around fooService everywhere, so you create a factory with a method Create(int x) and inject the service inside the factory.
    – Alex
    Commented Aug 14, 2014 at 14:29
  • 4
    @AlexG And then, you have to pass around IFactory everywhere instead of IFooService.
    – Euphoric
    Commented Aug 14, 2014 at 15:10
  • 3
    I agree with Euphoric; in my experience, objects that get injected into a graph from the top tend to be of a type that all lower-level objects need, and so passing IFooServices around is no big deal. Replacing one abstraction with another doesn't accomplish anything but further obfuscating the codebase.
    – KeithS
    Commented Aug 14, 2014 at 16:10
  • this looks totally irrelevant to the question asked, "Why should I use a factory class instead of direct object construction? When should I use public constructors, and when should I use factories?" See How to Answer
    – gnat
    Commented Mar 7, 2016 at 21:07
  • 1
    That's just the title of the question, I think you missed the rest of it. See last point of link provided ;). Commented Mar 7, 2016 at 21:56
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.

1
  • Also note; If the developer needs to provide a derived class with extra functionality (extra properties, initialization) the developer can do it. (assuming that the factory methods are overridable). The API author may also provide a work around for special customer needs. Commented Oct 31, 2018 at 16:26
-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.

1
  • 2
    this looks more like a tangential comment (see How to Answer), and it doesn't seem to offer anything substantial over points made and explained in prior 9 answers
    – gnat
    Commented Mar 7, 2016 at 21:05

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