Implementation of Bridge Design Pattern I made an implementation of the Bridge Pattern to handle ever-changing in crawler APIs that I'm using in my APP.

public interface CrawlerApi {
    // common constants to serveral implementations.
    String CHARSET = "ISO8859_1";
    int TIMEOUT = 20000;

    /**
     * Visit an url and return contents in String format.
     *
     * @param url
     * @return
     */
    String visit (String url);

    /**
     * Parse an Html code into an Navigable object that is provided by the API.
     *
     * @param htmlCode
     * @param documentType
     * @param &lt;T&gt;
     * @return
     */
    &lt;T&gt; T getDocument (String htmlCode, Class &lt;T&gt; documentType);

}




public class HtmlUnitCrawlerApi implements CrawlerApi {
    private WebClient webClient;

    public HtmlUnitCrawlerApi() {
        this.webClient = createWebClient();
    }


    @Override
    public String visit(String url) {
        Page p = null;
        try {
            p = webClient.getPage(url);
            return p.getWebResponse().getContentAsString(CHARSET);
        } catch (IOException e) {
            return "";
        }
    }

    @Override
    public &lt;T&gt; T getDocument(String htmlCode, Class&lt;T&gt; documentType) {
        throw new IllegalArgumentException("not implemented");
    }


    private WebClient createWebClient() {
        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_38);
        webClient.getOptions().setJavaScriptEnabled(true);
        webClient.getOptions().setCssEnabled(false);
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        webClient.setAjaxController(new NicelyResynchronizingAjaxController());
        webClient.waitForBackgroundJavaScript(TIMEOUT);
        return webClient;
    }

}




public class JsoupCrawlerApi implements CrawlerApi {
    public static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36";


    @Override
    public String visit(String url) {
        return connect.apply(url).html();
    }

    //I made this static because of the peculiarity of api that is static and because I have to
    //set some config parameters.
    private static Function&lt;String, Document&gt; connect = url -&gt; {
        try {
            return Jsoup.connect(url).timeout(TIMEOUT).userAgent(USER_AGENT).postDataCharset(CHARSET).get();
        } catch (IOException e) {
            return new Document("");
        }
    };

    private static Function&lt;String, Document&gt; parse = html -&gt; {
        Document doc = Jsoup.parse(html);
        doc.charset(Charset.forName(CHARSET));
        return doc;
    };


    @Override
    public &lt;T&gt; T getDocument(String htmlCode, Class&lt;T&gt; type) {
        return (T) parse.apply(htmlCode);
    }

}




Usage:

public class ApiClientExample {
    private CrawlerApi crawlerApi;

    public ApiClientExample(CrawlerApi crawlerApi) {
        this.crawlerApi = crawlerApi;
    }

    public void visit (String url){
        crawlerApi.visit(url);
    }
}


Concerns:

Is this code clean enough?

Is there anything that can be improved?
I looked at it twice and I do not see any kind of Bridge Pattern. I see a simple abstraction and some concrete implementations of it. "ApiClientExample" is maybe a wrapper. Technically it seems to me ok.

Nevertheless I'd like to comment on one semantic thing:

As the method "visit" is totally fine, the method "getDocument()" seems strange to me. Without totally rejecting it I'd make some research on the liskov substitution principle. You also should consider a wrong abstraction level or a wrong semantical assigment to the interface "CrawlerAPI" as the method "getDocument" is totally generic. Will the return value of "visit" be put into "getDocument()"? If so, the method is at the wrong place. You introduced a mental mapping and it would be more a cascading call than a method delared in the same interface.