Java 与第三方库解耦的设计模式
我正在尝试解耦第三方库的抽象类。我想公开一个新的抽象类,它将公开给用户,而不是库提供的类。Java 与第三方库解耦的设计模式,java,oop,design-patterns,Java,Oop,Design Patterns,我正在尝试解耦第三方库的抽象类。我想公开一个新的抽象类,它将公开给用户,而不是库提供的类。 我最初尝试使用适配器,但仍然在适配器类中添加第三方库的导入 我在下面添加了代码来解释我的新方法 // third party lib abstract class ThirdParty<S> { public abstract S doAction(S s); } // my goal here is to expose a different a
我最初尝试使用适配器,但仍然在适配器类中添加第三方库的导入 我在下面添加了代码来解释我的新方法
// third party lib
abstract class ThirdParty<S> {
public abstract S doAction(S s);
}
// my goal here is to expose a different abstract class which is decoupled from third party lib
// exposed to other modules, rather than exposing the third party lib
abstract class ExposedAbstractClass<S> {
public abstract S doAction(S source);
// get hold of type using guava lib
private final TypeToken<S> typeToken = new TypeToken<S>(getClass()) { };
public Class<S> getSourceClass() { return (Class<S>) typeToken.getClass()
}
// internal class
class Builder<S> extends ThirdPartyLib<S> {
ExposedAbstractClass exposed;
public Builder(ExposedAbstractClass exposed) {
this.exposed = exposed;
}
@Override
public S doAction(S s) {
return (S) exposed.doAction(s);
}
}
//my approach breaks here when i try to invoke builder
class InvokeThirdParty {
public void invoke (ExposedAbstractClass exposed) {
Class type = exposed.getSourceClass();
Builder<type> builder = new Builder(exposed); //doesn't work since Class is runtime type, and T is compile time type
}
}
//第三方库
抽象类第三方{
公开摘要的行为;
}
//我在这里的目标是公开一个与第三方lib解耦的不同抽象类
//公开给其他模块,而不是公开第三方库
抽象类ExposedAbstractClass{
公开摘要的作用(来源);
//使用guava lib获取类型
private final-TypeToken-TypeToken=new-TypeToken(getClass()){};
公共类getSourceClass(){return(Class)typeToken.getClass()
}
//内部类
类生成器扩展了ThirdPartyLib{
ExposedAbstractClass exposed;
公共生成器(ExposedAbstractClass exposed){
暴露的,暴露的;
}
@凌驾
公众的行动{
暴露的返回。执行操作;
}
}
//当我尝试调用生成器时,我的方法在这里中断
类调用第三方{
公共void调用(ExposedAbstractClass exposed){
Class type=exposed.getSourceClass();
Builder Builder=new Builder(exposed);//不工作,因为类是运行时类型,而t是编译时类型
}
}
这里关于遵循哪种设计模式的任何指导都将非常有用。我同意答案,您可以隔离第三方依赖关系,并使用适配器或桥接模式从那里调用第三方库。我相信这将是一个充分的解耦解决方案
但是,您的意图似乎是删除导入
,从而删除依赖关系
或者,在第三方
类上实现反射怎么样?
Java与面向反射的编程兼容。这允许您在运行时检查和检查类并动态调用它们的方法。这将消除第三方类的依赖关系和import
语句
一般来说,对于反射,您必须定位类并检查其方法。在本例中,我假设您了解doAction()
方法,它来自ThirdPartyClass
一个简单的Java反射示例,遵循代码摘录的思想:
不使用反射
//在此处某处导入第三方库语句
//用实现第三方方法的具体类实例化对象。从现在的代码来看,它应该是“生成器”。
第三方第三方对象=新的第三方对象();
//调用返回S对象的doAction方法
S foo=thirdPartyObject.doAction();
使用反射
//检查类,使用其路径找到它并实例化对象
ThirdParty thirdPartyObject=Class.forName(“classpath.to.ThirdPartyImp”).newInstance();//使用具体类进行实例化。
//寻找doAction方法。这是假设我们知道存在一个同名的方法。反射可以深入到不知道这些方法并让一些控制结构检查它们。
方法doAction=thirdPartyObject.getClass().getDeclaredMethod(“doAction”,新类[0]);
//调用Do操作并返回一个对象S。
S foo=thirdPartyObject.invoke(thirdPartyObject);
进一步阅读和注释
我最初尝试使用适配器,但仍然在适配器类中添加第三方库的导入
看起来没问题,因为适配器不仅包括应用程序端,还包括第三方端。您能解释一下这一点吗?@GauravJ是的,正如您所说,适配器将在公开类。我试图避免这种情况。我的目标是只公开一个独立的抽象类,它对第三方库没有任何依赖性。我还尝试使用桥接模式,但不太确定如何实现给定泛型的解耦。另外,也许我在这里的总体方法是错误的,即解耦第三方库并纠正错误方法是在这里使用适配器或facade,而不必担心与第三方解耦。您应该将第三方依赖关系一直推到应用程序的边缘。声明接口和内部类应该依赖于这些。我认为这样做没有任何错误。适配器模式或桥接模式是实现这一点的方法但您的应用程序中仍然存在类依赖关系。您的核心类不知道第三方(适配器或桥接器会知道)。如果您希望从应用程序中删除jar依赖关系,那么您需要使用类似于java.util.ServiceLocator的东西,但我怀疑这是否是您的用例。
// import ThirdPartyLibrary statement somewhere here
// Instantiating object with concrete class that implements methods from ThirdParty. From your code now, it would be "Builder".
ThirdParty<S> thirdPartyObject = new ThirdPartyImp<S>();
// Invoking doAction method which returns an S object
S foo = thirdPartyObject.doAction();
// Inspect the class finding it using its path and instantiating an object
ThirdParty<S> thirdPartyObject = Class.forName("classpath.to.ThirdPartyImp").newInstance(); // Using a concrete class to instantiate.
// Finding the doAction method. This is assuming we have knowledge that a method with this name exists. Reflection could go as deep as not knowing the methods and having some control structure inspecting them.
Method doAction = thirdPartyObject.getClass().getDeclaredMethod("doAction", new Class<?>[0]);
// Do action is invoked and it returns an object S.
S foo = thirdPartyObject.invoke(thirdPartyObject);