Beh quindi basta modificare l'interfaccia in

codice:
public interface SearchableBook {
    public Book searchByAuthorAndTitle(String author, String title);
}
L'utilità delle interfacce è che ti forniscono un contratto per un'operazione, fregandosene di come l'operazione viene implementata.

Ad esempio, potresti avere queste implementazioni:

codice:
public class RemoteLibrary implements SearchableBook {
    ...

    public Book searchByAuthorAndTitle(String author, String title) {
        // effettua la ricerca usando un oggetto remoto
    }
}


public class DatabaseLibrary implements SearchableBook {
    ...

    public Book searchByAuthorAndTitle(String author, String title) {
        // effettua la ricerca su un db
    }

}


public class CsvLibrary implements SearchableBook {
    ...

    public Book searchByAuthorAndTitle(String author, String title) {
        // effettua la ricerca su un file csv
    }
}
Nel tuo programma potrai fare una cosa del genere:

codice:
List<SearchableBook> list = new ArrayList<SearchableBook>();
list.add(new RemoteLibrary());
list.add(new DatabaseLibrary());
list.add(new CsvLibrary());

String author = ...
String title = ...

List<Book> books = new ArrayList<Book>();

for (SearchableBook sb : list) {
    Book book =  sb.searchByAuthorAndTitle(author, title);
    books.add(book);
}

...