我试图做一些聪明的事情。我正在创建一个天气应用程序,我们可以在其中使用另一个天气API替换weather API,而不会影响代码库。所以我开始使用包含多个模块的Maven项目。
我有一个包含Interface类和Base类的Base模块。 Interface类包含对API的调用(所有调用都是相似的,如果不完全相同),Base类包含API的属性(同样,所有属性都相似,如果不是精确的话)。
我为我们正在测试的两个天气API中的每一个都有一个模块,计划在我们开发应用程序时为新天气API创建更多模块。
最后,我创建了一个Core模块(包括main)来实现我想要测试的天气API的特定模块类。
现在,我知道最简单的方法是使用switch语句和枚举。但我想知道是否有更聪明的方法来做到这一点。也许使用模式?有什么建议吗?
这是我刚才描述的结构图:
这是UML表示:
这对我来说是一个学习过程。我想了解一个真正的Java Guru如何根据指定的配置实现适当的模块和类。
感谢您的建议。
答案 0 :(得分:3)
我试图做一些聪明的事情。我正在创建一个天气应用程序 我们可以用另一个天气API替换weather API 而不影响代码库。
如果没有进一步阅读,这第一个陈述让我想到plugin architecture design,但在软件设计过程中,决策不能匆忙,延迟越多,信息越多,信息越充分可以做出决定,现在只需记住一个想法。
我有一个包含Interface类和Base的Base模块 类。 Interface类包含对API 的调用(所有调用 类似,如果不是确切的话),Base类包含属性 API (同样,所有属性都相似,如果不准确的话)。
当不同的模块共享行为/状态时,最好重构它们并生成基本的抽象类和接口,这样你就走在正确的轨道上,但是,如果存在差异,那些不应该被重构进入基础模块。这背后的原因是简单,可维护性。如果您开始添加if子句或开关来处理这些差异,那么您刚刚介绍了模块之间的耦合,并且无论何时添加/修改其他模块,您都必须始终在基础模块中进行更改,而这不是可取的。
Open/Closed principle表示SOLID principles形式反映了这一点,它指出一个类应该为扩展打开但是为了修改而关闭。
因此,在您将基本模块中的常见行为重构后,每个新API都应该扩展基本模块,就像您一样。
最后,我创建了一个Core模块(包括main)来实现 我要测试的天气API的特定模块类。
现在,我知道最简单的方法是使用开关 陈述和枚举。但我想知道是否还有更多 聪明的方式来做到这一点。也许使用模式?有什么建议吗?
确实,使用开关,使其工作,但它根本不是一个干净的设计,出于同样的原因,在添加,修改或删除模块时,还需要修改此模块,以及代码可能会破坏。
一种可能的解决方案是将此责任委托给新组件,并使用像Abstract Factory这样的创建设计模式,它将提供实例化组件的接口,而无需指定其类。
至于架构,到目前为止,插件架构仍然有意义,但如果不同模块扩展基础合同添加更多功能会怎么样?一种选择是使用Facade pattern来调整模块调用并提供实现客户期望的接口的输出。
但话又说回来,根据提供的细节,这是我建议的解决方案,但应该仔细研究这个场景,以便能够确保这些是正确的工具。工作,并承诺他们。
答案 1 :(得分:3)
除了萨尔瓦多Juan Martinez's answer ......
要实现插件体系结构,Java Jar File Specification提供对服务提供者接口(SPI)的支持以及如何查找它们。
从Java 1.6开始。您可以使用ServiceLoader查找服务提供商。对于Java 1.5。而且你必须自己做或使用图书馆。例如。 commons-discovery
用法很简单。在您的情况下,在每个插件模块中放置一个META-INF/services/com.a2i.weatherbase.IWeather
文件。
在Weather Forecast IO
模块中,文件只应包含一行
com.a2i.weatherforecastio.ForecastIO
该行必须是IWeather
实现类的完整quallified名称。
对其他模块执行相同操作,您可以通过ServiceLoader
加载实现。
ServiceLoader<IWeather> weatherServicesLoader = ServiceLoader.load(IWeather.class);
Iterator<IWeather> weatherServices = weatherServicesLoader.iterator();
现在它取决于您的运行时类路径将找到多少服务。尝试从类路径中添加和删除模块jar
存档并运行您的应用程序。
修改强> 我写了一篇关于使用标准java的可插拔架构的博客。见http://www.link-intersystems.com/blog/2016/01/02/a-plug-in-architecture-implemented-with-java/
https://github.com/link-intersystems/blog/tree/master/java-plugin-architecture
也提供了源代码