Tomáš Zato
Tomáš Zato

Reputation: 53149

Only use library if available java

In C++ or C, you can do things like this:

#ifdef WINAPI
     public void showWindow(int cmdShow);
#endif

But in java, how can I define methods, that will only be compiled when user has enabled a library? I'm making a cross-platform application that uses certain native features which were not yet abstracted by JVM.

Also, I often make constructors that allow making my class from an object coming from some library. In that case, once the constructor is there, it force user to have that library. Instead, I'd like it to be only enabled when user has that library.

Upvotes: 4

Views: 1125

Answers (1)

Giovanni Botta
Giovanni Botta

Reputation: 9816

Java does not have the concept of macros or templates. Instead it has reflection and generics. In your case, you would use reflection. The idea is to code to interfaces and then at runtime figure out which implementation to use. If no suitable/custom implementation is found you need to fall back to some default (possibly a no-op implementation if you want nothing to happen by default).

The best way to support such architecture is to provide an entry point to your hierarchy of interfaces, i.e., a factory. The entry point will then provide to all clients the implementations they need. The entry point can use reflection to figure out which implementation you want, e.g.,

public final class LibraryManager {
  public static LibraryInterface find(String url) { ... }
}

The LibraryManager above figures out via reflection which implementation of LibraryInterface you want to obtain at runtime. The url can be simply the fully qualified class name of the required implementation of LibraryInterface, e.g., com.my.pack.MyLibraryInterfaceImpl.

To understand this in practice, take a look at JDBC's DriverManager: you get an implementation of Connection by providing the DriverManager.getConnection method with a jdbc URL. Behind the curtains, DriverManager uses reflection to find the right driver and returns the implementation needed. If the driver library for the given URL is not available you will get an exception.

In your case, the only modification you need to make to that pattern is to provide some default implementation if no library is specified. If the implementations rely on 3rd party libraries you are going to need to write appropriate adapters that use these, etc.

Note that in many cases you would actually return a factory to your library implementation so you can create many instances of the library objects. This works exactly the same way as above except you return some LibraryFactoryInterface instead.

Finally, if you use some kind of IoC or DI framework like Spring, you can define your implementation factory at configuration time to be injected in your application. A typical example and an alternative to DriverManager is DataSource. It's very common in a Spring application to define your DataSources in the configuration file. Spring will take care of wiring the DataSource into the objects that need to connect to the database.

Upvotes: 4

Related Questions