【问题标题】:Java - keeping multi-version application from splitting codebaseJava - 防止多版本应用程序拆分代码库
【发布时间】:2009-05-20 08:03:55
【问题描述】:
我正在编写一个应用程序,它将以几个不同的版本发布(最初将存在大约 10 个代码库变体,并且需要维护)。当然,98% 左右的代码在不同的系统中是相同的,保持代码库完整是有意义的。
我的问题是 - 这样做的首选方法是什么?例如,如果我有一个在某些版本(MyClassDifferent)中不同的类(MyClass),并且该类在几个地方被引用。我希望根据我正在编译的应用程序的版本来更改该引用,而不必拆分所有引用 MyClassDifferent 的类。预处理器宏会很好,但它们会使代码膨胀,而且 afaik 只有概念验证实现可用?
我正在考虑类似工厂模式的东西,以及每个应用程序的配置文件。有没有人有任何提示或指点?
【问题讨论】:
标签:
java
preprocessor
multiple-versions
【解决方案1】:
您走在正确的轨道上:工厂模式、配置等。
您还可以将系统特定功能放在单独的 jar 文件中,然后只需在核心 jar 文件旁边包含适当的 jar。
【解决方案2】:
我支持你的工厂方法,你应该仔细看看 maven 或 ant(取决于你使用的是什么)。
您可以部署不同的配置文件,根据参数/配置文件确定使用哪些类。
像 C/C++ 这样的预处理器 makros 不能直接用于 java。尽管也许可以通过构建脚本来模拟这一点。但我不会走那条路。我的建议是坚持工厂方法。
【解决方案3】:
幸运的是,您有多种选择
1) ServiceLoader(内置于 java6)将你的 API 类(如 MyClass)放在一个 jar 中,针对这个 API 编译你的应用程序。然后用 /META-INF/services/com.foo.MyClass 将 MyClass 的单独实现放在单独的 jar 中。 .然后,您可以维护应用程序的多个版本,只需保持 jar 的“分发”。您的“主”类只是一堆 ServiceLoader 调用
2) 与 1) 相同的架构,但将 META-INF 服务替换为 Spring 或 Guice 配置
3) OSGI
4) 你的解决方案
【解决方案4】:
查看 AbstractFactory 设计模式、“依赖注入”和“控制反转”。 Martin Fowler 写了关于这些here 的文章。
简而言之,您交付的 JAR 文件包含所有需要的组件。对于可以自定义的每个服务点,您都可以为服务定义一个接口。然后您编写该接口的一个或多个实现。要创建服务对象,您需要向 AbstractFactory 请求它,例如:
AbstractFactory factory = new AbstractFactory();
...
ServiceXYZ s = factory.newServiceXYZ();
s.doThis();
s.doThat();
在您的 AbstractFactory 中,您使用 Java 反射方法 Class.classForName() 和 SomeClassObject.newInstance() 构造适当的 ServiceXYZ 对象。 (这样做意味着您不必在 jar 文件中包含 ServiceXYZ 类,除非它有意义。您也可以正常构建对象。)
实际的类名是从每个站点唯一的属性文件中读取的。
您可以轻松推出自己的解决方案,或使用Spring、Guice 或Pico 等框架。