这个问题在某种程度上受到了previous question的启发。
我编写的大部分代码都与API有关,其性质必须易于扩展。一个常见的问题是我和我的团队其他人一起讨论如何处理插件,即可能扩展我们自己的接口和最终实现的类应该感觉像是解决方案的原子部分。我正在考虑以下类型的用例(使用汽车类比)
界面:
Car
提供的实施:
Ford
Audi
第三方实施:
Toyota
我们通常要求的是,CarDealer
类要知道Car
的所有现有实现,而第三方不必在配置文件中明确声明Car
。我一直在想的一个想法是让Car
的实现注册自己CarDealer
,但这会打开一个新的蠕虫,因为Toyota
(或任何其他实现)赢了' t被初始化,直到它们被明确引用,这是一个catch22。注释Car
的实现,然后浏览代码并使用相关注释初始化任何类也是一种方法,但我担心这可能会非常耗费资源。
我认为我们不能成为第一个遇到此问题的人,所以有没有任何已知的设计模式来解决它?
答案 0 :(得分:3)
看看java.util.ServiceLoader。基本上,您创建一个接口,然后该服务的所有实现者都可以包含文件/ META-INF / services /<完全限定名称的接口>列出他们jar中的所有实现。
然后可以使用ServiceLoader加载在类路径中发现的所有实现(例如,JDBC 4.0要求驱动程序也使用它来摆脱使用Class.forName(...)来加载驱动程序。)
答案 1 :(得分:0)
您可以为第三方类指定一个位置,然后使用Reflection来实例化它们。
或编写自定义类加载器
答案 2 :(得分:0)
在谈到这种情况时,我想到了两件事:
在抽象实现(或接口)中声明一个名为getName()的方法,在这种情况下,丰田将返回“丰田”等等。然后你可以考虑扫描整个类路径并收集作为Car(use this method for that)子类的类。最后使用(static?)工厂方法获取所有“Car实现”或按名称选择它们。使用反射来获取新对象。
有一个名为OSGi的平台,专门用于处理插件(使用OSGi服务)。当使用Spring DM与OSGi进行通信时,它变得非常容易使用。有两个主要的实现:Felix和Equinox。
总结一下:如果你可以选择平台 - 选择OSGi。如果你不能 - 我猜你必须扫描类路径。
答案 3 :(得分:0)
听起来你正在寻找Dependency Injection。 (奖金:维基百科使用汽车示例)