Why use creational patterns (in Java)?
The main reason for creational patterns is to separate the creation of an instance from its consumption.
That seems in the first place rather abstract, but has easy to see consequences.
1) You hide creational logic from the consument of an object-instance. As a consument you are not interested in how an instance is created. You only have a concrete demand (Service, Repository, etc.). Each demand is a dependency of your object. Which leads to
2) You are able to insert dependencies from the outside, aka dependency injection.
If you are able to inject/substitute dependencies of an object, you are better able to write unit-tests. Say you need the result of a complex DB-query or the result of several web-service-calls; you could easily inject those results from the outside or stub results.
Furthermore you could mock / stub out the creational objects itself, which could be used to deliver other mocks / stubs.
Better / more testable code leads to higher code coverage, which leads in the best case to better / higher code quality.
You could do your dependency injection by hand or use some kind of automation, e.g. Spring-framework or the like.
What unfavourable consequences could one face by not using creational patterns?
The downside of not using creational patterns should be clear from what was said above: It makes your code harder to understand and test.
real code examples:
Suppose you have a car, which itself has an engine. A typical way to implment it is this
public class Car {
Engine engine;
public void start(){
engine.start();
}
public void stop(){
engine.stop();
}
public Car(){
engine=new Engine();
}
}
public class Engine {
public void start(){
}
public void stop(){
}
}
You have a car, which instantiates its engine. Via the interface of the car, you are able to start/stop the car/engine.
This is bad in many ways:
1) you are not able to change the engine, the car runs with. That might not seem bad, since you intended the car to run only with the given engine
2) but, you could not swap the real engine_ out for a testengine.
You have to take two steps to improve the design:
1) separate the consumption of the engine from its use
2) use a factory pattern to encapsulate the creation of the engine
The improved car:
public class Car {
Engine engine;
public void start(){
engine.start();
}
public void stop(){
engine.stop();
}
public Car(Engine engine){
this.engine=engine;
}
}
The advantages are:
- ability to swap the engine for the car
- ability to swap the factory for the engine
So the whole creation of the car could be abstracted away with a builder:
public class CarBuilder {
EngineFactory engineFactory;
public Car build(){
return new Car(engineFactory.produceEngine());
}
public CarBuilder(EngineFactory engineFactory){
this.engineFactory=engineFactory;
}
}
Which itself could be mocked/stubbed.