3

This question is somewhat inspired by a previous question I've asked.

Most of the code I write has to do with an API, which by its nature has to be easily extendible. A common problem that I and the rest of my team wrestle with his how to handle plugins, i.e classes that may extend our own interfaces and in the final implementation should feel like an atomic part of the solution. I'm thinking in particular in the following kind of use case (to use a car analogy)

Interface:

Car

Provided Implementations:

Ford
Audi

3rd Party Implementations:

Toyota

What we usually require is that the class CarDealer be aware of all existing implementations of Car without the 3rd party being forced to explicitly declare Car in a configuration file. One idea I've been toying with is to let implementations of Car register themselves with CarDealer, but this opens up a new can of worms because Toyota (or any other implementation) won't be initialized until they're explicitly referenced, which is a catch22. Annotating implementations of Car and then going through the code and initializing any class with the relevant annotation is also a way to go, but I'm afraid that this might be terribly resource heavy.

I figure that we can't be the first ones with this issue, so are there any known design patterns to solve it out there?

Community
  • 1
  • 1
mikek
  • 1,555
  • 17
  • 30

4 Answers4

3

Take a look at java.util.ServiceLoader. Essentially you create an interface, and all implementers of the service can then include a file /META-INF/services/<fully-qualified-name-of-interface> listing all implementations in their jar.

The ServiceLoader can then be used to load all implementations discovered in the classpath (eg JDBC 4.0 requires drivers to use this as well to get rid of the use of Class.forName(...) to load drivers).

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
0

You could specify a location for just 3rd party classes and then use Reflection to instantiate them.

Or write a custom class loader

Aaron Gage
  • 2,373
  • 1
  • 16
  • 15
  • Using a fixed location is what we might end up with, but it's clumsier than I'd like. Could you elaborate on how a custom class loader would work? – mikek Oct 28 '11 at 12:39
0

There are 2 thing that comes into my mind when talking about this situation:

  1. Declare a method in your abstract implementation (or interface) called getName(), in this case Toyota would return "Toyota" and so on. Then you might consider scanning whole classpath and gather classes which are subclasses of Car (use this method for that). Finally use (static?) factory method to get all "Car implementations" or pick them by name. Use reflections to obtain new objects.

  2. There is platform called OSGi, which is created specially for handling plugins (by using OSGi Services). When using Spring DM to communicate with OSGi it becomes pretty easy to use. There are 2 main implementations: Felix and Equinox.

To summarize: if you can choose platform - pick OSGi. If you can not - I guess you would have to scan the classpath.

Sebastian Łaskawiec
  • 2,667
  • 15
  • 33
0

It sounds like you're looking for Dependency Injection. (Bonus: Wikipedia uses a car example)

Dave
  • 4,546
  • 2
  • 38
  • 59