Как написать универсальный Java API без перегрузки метода - PullRequest
0 голосов
/ 03 ноября 2018

У меня есть 2 (или более) источника данных, в которых хранится одно и то же; и я хочу написать интерфейс с методами, чтобы найти элементы в них. Пример:

public interface CarFinder {    
    public Car findById(String id);
}

Тогда я могу написать такой класс и использовать его:

public class CustomCarFinder implements CarFinder {

    public Car findById(String id) {
        ...
        return someCar;
    }
}
...
Car aCar = customCarFinder.findById("1");

CustomCarFinder знает, как подключиться к источнику данных и получить Car для меня. Проблема в том, что, в то время как для моего первого источника данных, CustomCarFinder может подключаться к нему каждый раз, когда я звоню "findById"; для второго источника данных клиент CarFinder знает, как получить соединение, а не CarFinder. Чтобы предоставить информацию о соединении CarFinder, я написал что-то вроде этого:

public interface CarFinder {

    public Car findById(String id, Object... context);

}

public class CustomCarFinder implements CarFinder {

    public Car findById(String id, Object... context) {
        //The Varargs (context) are not used in this version
        ...
        return someCar;
    }
}

public class AnotherCustomCarFinder implements CarFinder {

    public Car findById(String id, Object... context) {
        //Extract the connection here from the Varargs
        CustomConnection connection = (CustomConnection)context[0];
        ...
        //Somehow I find the car via this CustomConnection thing
        return someCar;
    }
}
...
Car aCar = customCarFinder.findById("1");
Car anotherCar = anotherCustomCarFinder.findById("1", aCustomConnection);

Видите ли, я использовал varargs, чтобы я мог использовать либо версию API. В первом случае, когда подключение не требуется, я все еще могу использовать:

Car aCar = customCarFinder.findById("1");

и если мне нужно предоставить соединение, то:

Car anotherCar = anotherCustomCarFinder.findById("1", aCustomConnection);

Классы Finder реализованы как Spring-синглтоны, поэтому они являются общими, и поэтому, чтобы избежать проблем с многопоточностью, они не сохраняют состояния, поэтому я не хочу устанавливать «Соединение» перед использованием методов; и именно поэтому я передаю Соединение как Varargs.

Есть ли другой способ сделать то же самое? Я получаю откат (от коллег) от использования Varargs, что я должен просто перегрузить метод "findById" с различными типами типов соединения. Я сопротивляюсь этому, потому что я не хочу, чтобы интерфейс отражал типы источников данных, к которым я подключаюсь. Я хочу, чтобы интерфейс, если вообще возможно, остался:

public Car findById(String id);

Мне также не нравятся Варарги, но я не уверен, как от них избавиться и все же добиться того, чего я хочу.

Ответы [ 2 ]

0 голосов
/ 04 ноября 2018

Я предполагаю, что вы можете использовать Java 8.

Если вам не нравится Varargs, вы можете вместо этого передать Supplier методу, например:

interface CarFinder {
    Car findById(String id, Supplier<Object> sup);
}

class CustomCarFinder implements CarFinder {
    public Car findById(String id, Supplier<Object> sup) {
        // ignore the sup
        // and the rest
    }
}

class AnotherCustomCarFinder implements CarFinder {
    public Car findById(String id, Supplier<Object> sup) {
        CustomConnection conn = (CustomConnection)sup.get();
        // and the rest
    }
}

Теперь вы можете использовать их:

customCarFinder.findById("1", () -> null);
anotherCustomCarFinder.findById("1", () -> customConnection);

Если вам также не нравится null (я полагаю), вы можете передать dummyConnection.

0 голосов
/ 03 ноября 2018

Varargs хороши, когда они необходимы, хотя в этом случае я думаю, что было бы лучше иметь установщик для соединения.

Чтобы сделать это доступным для всех потоков, вы можете использовать

public class AnotherCustomCarFinder implements CarFinder {
    private Pool<CustomConnection> connectionPool;

    public void setConnectionPool(Pool<CustomConnection> connectionPool) {
        this.connectionPool = connectionPool;
    }

    public Car findById(String id) {
        CustomConnection connection = connectionPool.acquire();
        //Somehow I find the car via this CustomConnection thing
        connectionPool.release(connection);
        return someCar;
    }
}

так вы можете написать

Car aCar = customCarFinder.findById("1");
Car anotherCar = anotherCustomCarFinder.findById("1");
...