在C ++或C中,您可以执行以下操作:
#ifdef WINAPI
public void showWindow(int cmdShow);
#endif
但是在java中,如何定义只在用户启用库时才编译的方法?我正在创建一个跨平台应用程序,它使用某些尚未被JVM抽象的本机功能。
另外,我经常制作构造函数,允许从来自某个库的对象创建我的类。在这种情况下,一旦构造函数存在,强制用户拥有该库。相反,我希望只有在用户拥有该库时才启用它。
答案 0 :(得分:4)
Java没有宏或模板的概念。相反,它有反射和泛型。在您的情况下,您将使用反射。我们的想法是编写接口,然后在运行时找出要使用的实现。如果找不到合适的/自定义实现,则需要回退到某个默认值(如果您希望默认情况下不发生任何操作,则可能是无操作实现)。
支持此类体系结构的最佳方法是为您的接口层次结构(即工厂)提供入口点。然后,入口点将为所有客户端提供他们所需的实现。入口点可以使用反射来确定您想要的实现,例如,
public final class LibraryManager {
public static LibraryInterface find(String url) { ... }
}
上面的LibraryManager
通过反映计算出你想在运行时获得的LibraryInterface
的实现。 url
可以只是LibraryInterface
所需实施的完全限定类名,例如com.my.pack.MyLibraryInterfaceImpl
。
要在实践中理解这一点,请查看JDBC的DriverManager
:通过为Connection
方法提供jdbc URL,您可以获得DriverManager.getConnection
的实现。在窗帘后面,DriverManager
使用反射来找到正确的驱动程序并返回所需的实现。如果给定URL的驱动程序库不可用,您将获得异常。
在您的情况下,您需要对该模式进行的唯一修改是在未指定库的情况下提供一些默认实现。如果实现依赖于第三方库,则需要编写使用这些库的适当适配器等。
请注意,在许多情况下,您实际上会将工厂返回到库实现,因此您可以创建库对象的许多实例。除了您返回一些LibraryFactoryInterface
之外,其效果与上述完全相同。
最后,如果你使用像Spring这样的某种IoC或DI框架,你可以在配置时定义你的实现工厂,以便在你的应用程序中注入。 DriverManager
的典型示例和替代方法是DataSource
。在Spring应用程序中,在配置文件中定义DataSource
是很常见的。 Spring将负责将DataSource
连接到需要连接到数据库的对象。