10 Using services to decouple modules

 

This chapter covers:

  • how services improve the overall project design
  • creating services, consumers, and providers in the JPMS
  • using the ServiceLoader to consume services
  • developing well-designed services
  • deploying services in plain and modular JARs across different Java versions

Up to now we represented relationships between modules with requires directives where the depending module has to reference each specific dependency by name. As section 3.2 explains in depth, this lies at the very heart of reliable configuration. But is this specificity always the best way to go?

If we were talking about classes instead of modules, would you be happy with always depending on concrete types? Or with having to instantiate each dependency in the class that needs it? If you like design patterns like inversion of control or dependency injection, you should be vigorously shaking your head at this point. Compare listings 10.1 and 10.2—doesn’t the second look better? It allows the caller to pick the stream that gets to be awesome and even gives him the freedom to choose any InputStream implementation he likes.

10.1  Services in the Java Platform Module System

10.1.1  Using, providing, and consuming services

10.1.2  Module resolution for services

10.2  Designing services well

10.2.1  Types that can be services

10.2.2  Using factories as services

10.2.3  Isolating consumers from global state

10.2.4  Organizing services, consumers, and providers into modules

10.2.5  Using services to break cyclic dependencies

10.2.6  Declaring services across different Java versions

10.3  Accessing services with the ServiceLoader API

sitemap