Когда использовать интерфейсы Single method в Java
Я видел во многих библиотеках, таких как Spring
, которые используют в них много интерфейсов с одиночными методами BeanNameAware
и т.д.
И класс реализации будет реализовывать множество интерфейсов с помощью отдельных методов.
В каких сценариях имеет смысл поддерживать единый интерфейс метода? Это делается для того, чтобы не сделать один единый интерфейс громоздким, например ResultSet
? Или есть какой-то дизайн, который защищает использование этих типов интерфейсов?
Ответы
Ответ 1
С Java 8 поддержание интерфейса одного метода весьма полезно, поскольку интерфейсы с одним интерфейсом позволят использовать блокировки и "указатели на функции". Таким образом, всякий раз, когда ваш код написан против одного интерфейса метода, клиентский код может передать закрытие или метод (который должен иметь совместимую подпись для метода, объявленного в интерфейсе одного метода), вместо того, чтобы создавать анонимный класс. Напротив, если вы создадите один интерфейс с несколькими способами, клиентский код не будет иметь такой возможности. Он всегда должен использовать класс, который реализует все методы интерфейса.
Итак, как общее правило, можно сказать: если класс, который предоставляет только один метод для кода клиента, может быть полезен для какого-либо клиента, то использование одного метода для этого метода является хорошей идеей. Примером встречного примера является интерфейс Iterator
: здесь было бы нецелесообразно иметь только метод next()
без метода hasNext()
. Поскольку класс, который реализует только один из этих методов, бесполезен, разделение этого интерфейса здесь не очень хорошо.
Пример:
interface SingleMethod{ //The single method interface
void foo(int i);
}
class X implements SingleMethod { //A class implementing it (and probably other ones)
void foo(int i){...}
}
class Y { //An unrelated class that has methods with matching signature
void bar(int i){...}
static void bar2(int i){...}
}
class Framework{ // A framework that uses the interface
//Takes a single method object and does something with it
//(probably invoking the method)
void consume(SingleMethod m){...}
}
class Client{ //Client code that uses the framework
Framework f = ...;
X x = new X();
Y y = new Y();
f.consume(x); //Fine, also in Java 7
//Java 8
//ALL these calls are only possible since SingleMethod has only ONE method!
f.consume(y::bar); //Simply hand in a method. Object y is bound implicitly
f.consume(Y::bar2); //Static methods are fine, too
f.consume(i -> { System.out.println(i); }) //lambda expression. Super concise.
//This is the only way if the interface has MORE THAN ONE method:
//Calling Y.bar2 Without that closure stuff (super verbose)
f.consume(new SingleMethod(){
@Override void foo(int i){ Y.bar2(i); }
});
}
Ответ 2
Интерфейсы только с одним (или несколькими) методами являются ключом к высокоэффективному шаблону стратегии, который является "некоторым стандартом дизайна, который защищает использование этих типов интерфейсов".
Другим распространенным сценарием является запрос обратного вызова. Foo вызывает Bar как асинхронную задачу, и когда Bar заканчивается чем-то, результат отправляется обратно в Foo, используя обратный вызов, который может быть интерфейсом, содержащим только один метод. (Например, это многие слушатели в Android, Слушатели событий в Swing...)
Кроме того, если у вас есть два класса, которые тесно связаны друг с другом (позвольте им назвать Foo и Bar). Foo использует почти все методы Bar, но для Bar требуется только некоторые из них из Foo. Foo может реализовать FooInterface
, который затем отправляется в Bar. Теперь связь слабее, потому что Bar знает только об FooInterface, но не заботится о других методах, которые содержит класс реализации.
Ответ 3
Он определенно хорош, чтобы быть подозрительным к интерфейсам с одним методом, поэтому +1 для вопроса.
Но вы знаете, вы создаете интерфейс для поддержки связки связанных методов. Если у вас действительно есть метод, который явно не связан ни с одним из других методов, то интерфейс с одним методом оправдан.
В случае подозрения, где вы делаете шаг назад и говорите: "Теперь этот метод действительно не связан ни с чем другим?" Если вы счастливы, что это не так, значит, это "правильное" время.
Ответ 4
В каких сценариях имеет смысл поддерживать единые интерфейсы методов?
В таких сценариях, когда вам нужен интерфейс только с одним методом.
Интерфейсы используются для инкапсуляции общего поведения нескольких классов. Поэтому, если у вас есть несколько мест в вашем коде, где вам нужно вызвать только ограниченный набор методов класса, пришло время ввести интерфейс. Количество методов зависит от того, что именно вам нужно вызвать. Иногда вам нужен один метод, иногда два или больше, иногда вам вообще не нужны методы. Важно то, что вы можете отделить поведение от реализации.
Ответ 5
Favor Composition over Inheritance
учебник книги Head First Design Pattern
рекомендует этот подход для динамического добавления функциональности в класс. Возьмем ниже случай:
public interface Quackable {
public void quack();
}
public class Quacks implements Quackable {
public void quack(){
//quack behavior
}
}
public class DontQuack implements Quackable {
public void quack(){
//dont quack
}
}
public class QuackableDuck{
Quackable quack; //add behavior dynamicall
}
Итак, класс QuackableDuck может динамически добавлять функцию.
quack = new Quacks();
//or
quack = new DontQuack();
Таким же образом вы можете добавить динамическое поведение нескольких классов в класс.
Ответ 6
Вы создаете интерфейсы не в соответствии с количеством методов в нем, а для определения поведения, ожидаемого компонентами ваших систем, для предоставления единой ответственности своим соседям. Если вы будете следовать этому простому принципу/правилу, вы можете или не можете иметь отдельные интерфейсы метода, в зависимости от ответственности, которую вы определяете. Мне нравится, чтобы тесты были глупыми, и приложение очень гибкое, поэтому я обычно имею много таких