【问题标题】:Design Pattern to Merge Functionality of Two+ External Libraries合并两个+外部库功能的设计模式
【发布时间】:2020-09-03 02:56:05
【问题描述】:

我正在使用两个第三方库来执行类似的功能。我需要能够决定在运行时使用哪个库(每个库在不同类型的任务中都表现出色,我只知道运行时特定任务需要哪个库)。

我正在尝试创建一个类,以便可以在运行时动态调用特定库的功能。最初,我考虑使用适配器模式,但问题是两个库都返回不同类型的对象,并且适配器模式只有在接口(或签名)相同时才有用。

举一个具体的例子,Selenium 框架允许我通过在 WebDriver 实例上调用方法 driver.findElement(By.Xpath("XPath")) 从页面中提取 Web 元素。同样,XSoup 框架(JSoup 的扩展)允许我通过调用Xsoup. compile( "XPath" ).evaluate(doc ).getElements(); 来执行相同的功能。这两种方法的功能在语义上是等效的 - 但是它们都返回(并期望)两种不同类型的对象(WebDriver 返回 WebElementXSoup 返回 Element 的实例 - 两个不同的对象。类似地,@ 987654331@ 期望 driver 对象和 XSoup 期望 document 对象作为参数传入)。

我的目标是通过调用单个方法(例如本例中的getElement())来合并两个框架的功能,并让该方法处理调用正确库/框架的细节(基于传递的一些参数以方法为例)

什么设计模式可用于在运行时合并两个库的功能?

谢谢

【问题讨论】:

  • 仅仅将逻辑封装到一个方法中还不够吗?它的签名是一个facade来访问所需的功能?访问此方法的客户端代码将不需要依赖这两个库。如果您发布了到目前为止的代码并澄清了您认为缺少的内容,那么回答问题会更容易。

标签: java oop design-patterns


【解决方案1】:

您在适配器模式的正确轨道上。听起来你需要两个级别。

您首先需要定义一个能够包装 WebElement 和 Element 的通用接口:

public interface MyElement {
    String getText();
}  

public class SeleniumElement implements MyElement {
    private WebElement element;

    public SeleniumElement(WebElement element) {
        this.element = element;
    }

    public String getText() {
        return element.getText();
    }
}

public class XSoupElement implements MyElement {
    private Element element;

    public XSoupElement(Element element) {
        this.element = element;
    }

    public String getText() {
        return element.text();
    }
}

然后,您需要定义一个返回这些值的接口,并为 XSoup 和您正在使用的任何其他库提供一个实现。实现只会包装库中的返回值:

public interface Driver {
    public MyElement findByXpath(String xpath);
}

public class MySeleniumDriver implements Driver {
    public MyElement findByXpath(String xpath) {
        return new SeleniumElement(driver.findElement(By.Xpath(xpath)));
    }
}

public class MyXSoupDriver implements Driver {
    public MyElement findByXpath(String xpath) {
        return new XSoupElement(Xsoup.compile(xpath).evaluate(doc).getElement());
    }
}

然后在运行时你可以改变你使用的框架:

Driver myDriver = isSeliniumBetter ? new MySeliniumDriver() : MyXSoupDriver();

String text = myDriver.findByXPath("xpath").getText();

【讨论】:

  • 谢谢。如果我只想返回一个“统一”元素(不执行 'getText()' 方法)怎么办?
  • 你能更好地描述你所说的“统一”是什么意思吗?你想如何在代码中使用它? MyElement 的重点是实际上将两个库统一在一个通用接口后面,您可以使用该接口在运行时切换实现。如果不提供自己的通用接口,就无法像这样统一两个不同的接口,类型系统不允许这样做。如果你举个例子,可能会有更好的模式,但取决于你的使用。
猜你喜欢
  • 2012-07-05
  • 2012-05-01
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多