To set the stage, I am trying to do pure dependency injection for a Java Library I am creating to make it more testable. As it is a library, I want to do pure dependency injection without creating a DI container/composition root as discussed by Mark Seemann in his blog posts*. The problem I am running into is that I have some visitor classes that must contain state (an example illustrating the concept is below). Would it be cleaner to inject these or just declare them using the new keyword? The only problem I see with injecting them is that I would need a function to clear the state of the visitor after every call vs. using new I would not have to. Is there any best practice for this?
public class CarServiceBuilder { public CarService buildCarService(){ CarPartPrinter carPartPrinter = new CatPartPrinter(); CarService carService = new CarService(carPartPrinter); return carService; } } public class CarService { private final CarPartPrinter printParts; public CarService(CarPartPrinter carPartPrinter){ this.carPartPrinter = carPartPrinter; } public void printParts(Car car){ CarVisitor carVisitor = new CarVisitor(); car.accept(carVisitor); List<Part> parts = carVisitor.getParts(); carPartPrinter.printParts(parts); } } public class CarVisitor extends Visitor { private List<Parts> parts; public CarVisitor(){ parts = new ArrayList<>(); } @Override public void visit(Part part){ parts.add(part); } }
VS.
public class CarServiceBuilder { public CarService buildCarService(){ CarVisitor carVisitor = new CarVisitor(); CarPartPrinter carPartPrinter = new CatPartPrinter(); CarService carService = new CarService(carVisitor, carPartPrinter); return carService; } } public class CarService { private final CarVisitor carVisitor; private final CarPartPrinter printParts; public CarService(CarVisitor carVisitor, CarPartPrinter carPartPrinter){ this.carVisitor = carVisitor; this.carPartPrinter = carPartPrinter; } public void printParts(Car car){ car.accept(carVisitor); List<Part> parts = carVisitor.getParts(); carPartPrinter.printParts(parts); carVisitor.clearState(); } } public class CarVisitor extends Visitor { private List<Parts> parts; public CarVisitor(){ parts = new ArrayList<>(); } @Override public void visit(Part part){ parts.add(part); } public void clearState(){ parts = new ArrayList<>(); } }
Related blog posts: