2017-03-19 8 views
2

Ich verwende zwei Bibliotheken von Drittanbietern, um ähnliche Funktionen auszuführen. Ich muss in der Lage sein zu entscheiden, welche Bibliothek zur Laufzeit verwendet werden soll (jeder ist bei einer anderen Art von Aufgabe überlegen und ich weiß nur, welcher für eine bestimmte Aufgabe zur Laufzeit benötigt wird).Entwurfsmuster zum Zusammenführen von zwei + externen Bibliotheken

Ich versuche, eine einzelne Klasse zu erstellen, damit ich zur Laufzeit die Funktionalität einer bestimmten Bibliothek dynamisch aufrufen konnte. Anfangs dachte ich über die Verwendung des Adaptermusters nach, aber das Problem ist, dass beide Bibliotheken unterschiedliche Arten von Objekten zurückgeben und das Adaptermuster nur dann nützlich ist, wenn die Schnittstelle (oder Signatur) die gleiche ist.

Um ein spezifisches Beispiel zu geben, erlaubt das Selenium Framework mir ein Webelement von einer Seite zu extrahieren, indem ich die Methode driver.findElement(By.Xpath("XPath")) auf einer WebDriver Instanz aufruft. In ähnlicher Weise ermöglicht das XSoup Framework (eine Erweiterung von JSoup), dass ich die gleiche Funktionalität durch Aufruf von Xsoup. compile("XPath").evaluate(doc).getElements(); ausführen kann. Die Funktionalität beider Methoden semantisch äquivalent sind - aber sie beide Rückkehr (und erwarten) zwei verschiedene Arten von Objekten (WebDriver gibt ein WebElement und XSoup kehrt eine Instanz von Element -. Zwei verschiedene Objekte Ebenso erwartet WebDriver ein driver Objekt und XSoup erwartet ein document Objekt, das als Parameter übergeben werden soll).

Mein Ziel ist es, die Funktionalität der beiden Frameworks durch den Aufruf einer einzigen Methode (wie getElement() in diesem Fall) zusammenzuführen und die Methode mit den Details des Aufrufs der richtigen Bibliothek/Framework (basierend auf einem Parameter übergeben) die Methode für Beispiel)

Welches Entwurfsmuster könnte verwendet werden, um die Funktionalität beider Bibliotheken zur Laufzeit zusammenzuführen?

Danke

+0

Ist es nicht genug, um einfach die Logik in einer einzigen Methode kapseln deren Signatur ist eine _Facade_ für den Zugriff auf die erforderliche Funktionalität? Client-Code, der auf diese Methode zugreift, muss dann nicht von diesen beiden Bibliotheken abhängig sein. Wenn Sie den Code, den Sie bisher hatten, gepostet haben und geklärt haben, was Ihrer Meinung nach fehlt, wäre es einfacher, die Frage zu beantworten. –

Antwort

1

Sie sind mit dem Adaptermuster auf dem richtigen Weg. Es klingt, als würden Sie zwei Ebenen davon brauchen.

Sie werden zuerst müssen eine gemeinsame Schnittstelle definieren, die eine WebElement der Verpackung und ein Element, ist:

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(); 
    } 
} 

Dann benötigen Sie eine Schnittstelle definieren, die diese Werte zurückgibt und eine Implementierung haben für XSoup und alle anderen Bibliotheken, die Sie verwenden. Die Implementierungen wickeln nur die Rückgabewerte aus der Bibliothek:

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()); 
    } 
} 

zur Laufzeit Dann können Sie den Rahmen, den Sie verwenden ändern:

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

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

Danke. Was, wenn ich nur ein "vereinheitlichtes" Element (ohne die Methode 'getText()') zurückgeben wollte, sehe ich nicht, wie das helfen würde .. es sei denn, ich habe etwas verpasst. Wie kombinierst du WebElement & Element Objekte ? –

+0

Können Sie besser beschreiben, was Sie mit "vereinheitlicht" meinen? Wie möchten Sie es im Code verwenden? Der Punkt von MyElement besteht darin, die beiden Bibliotheken hinter einer gemeinsamen Schnittstelle zu vereinen, mit der Sie Implementierungen zur Laufzeit wechseln können. Sie können zwei verschiedene Schnittstellen nicht zusammenführen, ohne eine eigene gemeinsame Schnittstelle zur Verfügung zu stellen, das Typsystem lässt dies nicht zu.Es kann jedoch ein etwas besseres Muster geben, abhängig von Ihrer Verwendung, wenn Sie ein Beispiel geben. –

Verwandte Themen