2017-03-19 72 views
2

我正在使用兩個第三方庫來執行類似的功能。我需要能夠決定在運行時使用哪個庫(每個庫在不同類型的任務中都很優秀,我只知道在運行時需要哪一個庫用於特定任務)。合併兩個+外部庫的功能的設計模式

我試圖創建一個類,所以我可以在運行時動態調用特定庫的功能。最初,我想過使用適配器模式,但問題是兩個庫都返回不同類型的對象,並且適配器模式只在接口(或簽名)相同時纔有用。

爲了提供一個具體的例子,Selenium框架允許我通過調用方法driver.findElement(By.Xpath("XPath"))上一個WebDriver實例來提取頁面的網頁元素。同樣,XSoup框架(JSoup的擴展)允許我通過調用Xsoup. compile("XPath").evaluate(doc).getElements();來執行相同的功能。這兩種方法的功能是語義上等價 - 但他們都返回(並期望)兩種不同類型的對象(WebDriver返回WebElementXSoup回報Element一個實例 - 兩個不同的對象同樣,WebDriver期望一個driver對象和XSoup預計一document要作爲參數傳入的對象)。

我的目標是通過調用單個方法(如本例中的getElement())來合併兩個框架的功能,並讓該方法處理調用正確的庫/框架的細節(基於傳遞給例如方法)

什麼樣的設計模式可以用來在運行時合併兩個庫的功能?

謝謝

+0

它是不夠的,簡單的邏輯封裝到一個單一的方法,其簽名是用於訪問所需功能的_facade_?訪問此方法的客戶端代碼將不需要依賴這兩個庫。如果您發佈了迄今爲止的代碼並澄清了您認爲缺乏的內容,那麼回答該問題會更容易。 –

回答

1

你在適配器模式的正確軌道上。聽起來你需要兩層。

首先,您需要定義一個通用的接口,它能夠包裹一個WebElement和元素:

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 MySelenium Driver 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(); 
+0

謝謝。如果我只是想返回一個「統一」元素(沒有執行方法'getText()'),我不明白這將如何幫助..除非我錯過了什麼......如何結合WebElement&Element對象? –

+0

你能更好地描述你「統一」的含義嗎?你想如何在代碼中使用它? MyElement的意義在於將兩個庫統一在一個可用於在運行時切換實現的通用接口背後。你不能統一兩個不同的接口,而不提供你自己的通用接口,類型系統不允許它。如果你舉一個例子,根據你的使用情況,可能會有一個稍好的模式。 –