0

After reading and watching some videos on dependency injection I still don't understand how to use it properly without breaking encapsulation.

Note: I read How to use Dependency Injection without breaking encapsulation? but I'm still not 100% sure.

My code is a very simple implementation of thread pool, which contains objects of class Worker which is a package-private class that I don't want to expose to the outside world (and it's really non of their concern).

My thread pool constructor requires a parameter Worker[] workers (I don't need a factory since I know in advance exactly how many workers I need).

Since my Worker class is package-private I thought that the right way to construct the thread factory would be to implement a static factory method in the ThreadPool class as follows:

public static ThreadPool createThreadPool(int numOfWorkers, 
                                          BlockingQueue<Runnable> jobQueue, 
                                          ThreadFactory threadFactory) {

    Worker workers[] = new Worker[numOfWorkers];
    for (int i = 0; i < workers.length; i++) {
        workers[i] = new Worker(jobQueue, threadFactory, i);
        // worker needs the factory in order to provide itself as Runnable
    }
    return new ThreadPool(workers, jobQueue);
}

So, is creating all these new objects in the static factory method the right way to hide the Worker class from other packages, or is there something I'm missing here?

Community
  • 1
  • 1
traveh
  • 2,700
  • 3
  • 27
  • 44

1 Answers1

0

Dependency Injection would mean hiding the creation of the Workers from the ThreadPool. Ideally, Runnables should be passed into the ThreadPool constructor, and the ThreadPool shouldn't even know that the Runnables happen to be Workers.

Creation of the Workers should occur in the composition root.

Community
  • 1
  • 1
jaco0646
  • 15,303
  • 7
  • 59
  • 83
  • I don't understand. Why would I want to expose the `Worker` class to the outside world when it's only relevant to the thread pool itself? (It's an implementation detail of the thread pool) – traveh Aug 18 '16 at 08:49
  • `Worker` is a concrete class. Following the [Dependency Inversion Principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle), nothing should depend on concrete classes (except the composition root). – jaco0646 Aug 18 '16 at 15:41
  • Static methods, including static factory methods, will always [violate](http://stackoverflow.com/questions/4002201/why-arent-static-methods-considered-good-oo-practice) object-oriented principles. That doesn't mean you have to doggedly follow object-oriented principles. Indeed, static factories are common; but if you're trying to loosen coupling via dependency injection, the static factory will do the opposite. It tightly couples `ThreadPool` and `Worker` together. – jaco0646 Aug 18 '16 at 15:54