So there's a fancy new Hamburger
class that is easy to test, but it's currently awkward to work with. Instantiating a Hamburger
requires:
const hamburger = new Hamburger(new Bun(), new Patty('beef'), new Toppings([]));
That's a lot of work to create a Hamburger
, and now all the different pieces of code that make Hamburger
s have to understand how Bun
, Patty
and Toppings
get instantiated.
One approach to dealing with this new problem might be to make a factory function like so:
function makeHamburger() {
const bun = new Bun();
const patty = new Patty('beef');
const toppings = new Toppings(['lettuce', 'tomato', 'pickles']);
return new Hamburger(bun, patty, toppings);
}
This is an improvement, but when more complex Hamburger
s need to be created this factory will become confusing. The factory is also responsible for knowing how to create four different components. This is a lot for one function.
This is where a dependency injection framework can help. DI Frameworks have the concept of an Injector
object. An Injector is a lot like the factory function above, but more general, and powerful. Instead of one giant factory function, an Injector has a factory, or recipe (pun intended) for a collection of objects. With an Injector
, creating a Hamburger
could be as easy as:
const injector = new Injector([Hamburger, Bun, Patty, Toppings]);
const burger = injector.get(Hamburger);