【问题标题】:Design pattern to decouple from third party lib与第三方库解耦的设计模式
【发布时间】:2017-02-13 04:47:28
【问题描述】:

我正在尝试解耦第三方库的抽象类。我想公开一个新的抽象类,它将向用户公开,而不是库提供的类。
我最初尝试使用适配器,但仍然在适配器类中添加第三方库的导入。

我在下面添加了代码来解释我的方法。

   // 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 
       }
   }

任何关于此处遵循哪种设计模式的指导都会非常有帮助。

【问题讨论】:

  • I initially tried using an adapter but that stills add the import for the third party lib in the adapter class 看起来没问题,因为适配器不仅包括您的应用程序端,还包括第三方端。你能解释一下这一点吗?
  • @GauravJ 是的,正如你所说,适配器会在暴露的类中引入第三方端。我试图避免这种情况。我的目标是只公开一个独立的抽象类,它对第三方库没有任何依赖。我也尝试使用桥接模式,但不太确定如何实现给定泛型的解耦。另外,也许我在这里解耦第三方库的总体方法是错误的,正确的方法是在这里使用适配器或外观,而不用担心解耦第三方。
  • 您应该将您的第三方依赖项一直推送到应用程序的边缘。声明接口和你的内部类应该依赖于那些。我认为这样做没有任何问题。适配器模式或桥接模式是实现此目的的方法,但您的应用程序中仍然存在类依赖关系。您的核心类不会知道第三方(您的适配器或网桥会知道)。如果您希望从应用程序中删除 jar 依赖项,那么您需要使用类似于 java.util.ServiceLocator 的东西,但我怀疑这是您的用例。

标签: java oop design-patterns


【解决方案1】:

我同意GuaravJ 的回答,您可以隔离第三方依赖项并使用适配器或桥接模式从那里调用第三方库。我相信这将是一个足够的解耦解决方案。

但是,您的意图似乎是删除import,因此依赖?

作为替代方案,如何在 ThirdParty 类上实现 Reflection

Java 与 面向反射的编程 兼容。这使您可以检查和检查类并在运行时动态调用它们的方法。它将消除 ThirdParty 类的依赖关系和 import 语句。

一般来说,使用反射,您必须找到类并检查其方法。在这种情况下,我假设知道ThirdPartyClass 中的doAction() 方法。

一个简单的 Java 反射示例,遵循您的代码摘录的想法:

不使用反射

// 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);

进一步阅读和笔记

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2013-03-26
    • 2017-07-14
    相关资源
    最近更新 更多