Java - 防止多版本应用程序拆分代码库
我正在编写一个应用程序,该应用程序将以多个不同版本发布(最初将存在大约 10 个代码库变体,并且需要维护)。 当然,不同系统中 98% 左右的代码是相同的,保持代码库完整是有意义的。
我的问题是 - 执行此操作的首选方法是什么? 例如,如果我有一个在某些版本中不同的类 (MyClass) (MyClassDifferent),并且该类在几个地方被引用。 我希望该引用根据我正在编译的应用程序的版本进行更改,而不是必须拆分引用 MyClassDifferent 的所有类。 预处理器宏会很好,但它们会使代码变得臃肿,而且只有概念验证可用吗?
我正在考虑类似工厂模式的东西,加上每个应用程序的配置文件。 有人有任何提示或指示吗?
I am writing an application that will ship in several different versions (initially around 10 variations of the code base will exist, and will need to be maintained). Of course, 98% or so of the code will be the same amongst the different systems, and it makes sense to keep the code base intact.
My question is - what would be the preferred way to do this? If I for instance have a class (MyClass) that is different in some versions (MyClassDifferent), and that class is referenced at a couple of places. I would like for that reference to change depending on what version of the application I am compiling, rather than having to split all the classes referring to MyClassDifferent too. Preprocessor macros would be nice, but they bloat the code and afaik there are only proof of concept implementations available?
I am considering something like a factory-pattern, coupled with a configuration file for each application. Does anyone have any tips or pointers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您走在正确的轨道上:工厂模式、配置等。
您还可以将系统特定功能放入单独的 jar 文件中,然后您只需要在核心 jar 文件中包含适当的 jar 即可。
You are on the right track: Factory patterns, configuration etc.
You could also put the system specific features in separate jar files and then you would only need to include the appropriate jar alongside your core jar file.
我支持你的工厂方法,你应该仔细看看 Maven 或 ant (取决于你使用的是什么)。
您可以部署不同的配置文件,根据参数/配置文件确定使用哪些类。
像 C/C++ 这样的预处理器 makros 不能直接用于 java。 尽管也许可以通过构建脚本来模拟这一点。 但我不会走那条路。 我的建议是坚持工厂方法。
I'd second your factory approach and you should have a closer look at maven or ant (depending on what you are using).
You can deploy the different configuration files that determine which classes are used based on parameters/profiles.
Preprocessor makros like C/C++ have are not available directly for java. Although maybe it's possible to emulate this via build scripts. But I'd not go down that road. My suggestion is stick with the factory approach.
幸运的是,你有几个选择
1) ServiceLoader (java6 中内置)将您的 API 类(例如 MyClass)放入 jar 中,然后针对此 API 编译您的应用程序。 然后将 MyClass 的单独实现放入 /META-INF/services/com.foo.MyClass 的单独 jar 中。 。 然后,您可以维护应用程序的多个版本,只需保留 jar 的“分布”即可。 你的“主”类只是一堆 ServiceLoader 调用
2) 与 1) 相同的架构,但用 Spring 或 Guice 配置替换 META-INF 服务
3) OSGI
4) 你的解决方案
fortunately you have several options
1) ServiceLoader (builtin in java6) put your API class like MyClass in a jar, the compile your application against this API. Then put a separate implementation of MyClass in a separate jar with /META-INF/services/com.foo.MyClass. . Then you can maintain several version of your application simply keeping a "distribution" of jars. Your "main" class is just a bunch of ServiceLoader calls
2) same architecture of 1) but replacing META-INF services with Spring or Guice config
3) OSGI
4) your solution
查找 AbstractFactory 设计模式、“依赖注入”和“控制反转”。 Martin Fowler 在此处撰写了有关这些内容的文章。
简而言之,您可以发送包含所有所需组件的 JAR 文件。 对于每个可以自定义的服务点,您可以为该服务定义一个接口。 然后,您编写该接口的一个或多个实现。 要创建服务对象,您需要向 AbstractFactory 请求它,例如:
在 AbstractFactory 内部,您使用 Java 反射方法 Class.classForName() 和 SomeClassObject.newInstance() 构造适当的 ServiceXYZ 对象。 (这样做意味着您不必在 jar 文件中包含 ServiceXYZ 类,除非它有意义。您也可以正常构建对象。)
实际的类名是从每个站点唯一的属性文件中读取的。
您可以轻松地推出自己的解决方案,或者使用像 Spring、Guice,或
Look up the AbstractFactory design pattern, "Dependency Injection", and "Inversion of Control". Martin Fowler writes about these here.
Briefly, you ship JAR files with all the needed components. For each service point that can be customized, you define an Interface for the service. Then you write one or more implementations of that Interface. To create a service object, you ask an AbstractFactory for it, eg:
Inside your AbstractFactory you construct the appropriate ServiceXYZ object using the Java reflection method Class.classForName(), and SomeClassObject.newInstance(). (Doing it this way means you don't have to have the ServiceXYZ class in the jar files unless it makes sense. You can also build the objects normally.)
The actual class names are read in from a properties file unique to each site.
You can roll your own solution easily enough, or use a framework like Spring, Guice, or Pico.