Мой вопрос - это общий вопрос дизайна на Java. В типичных конструкциях на базе контроллера (например, MVC) контроллеры обычно создают экземпляры действий и вызывают метод, реализованный из интерфейса (скажем, execute() интерфейса Action).
Почему нам нужно создавать ненужные объекты, почему бы не использовать статический вызов и исключить необходимость реализации интерфейса?
как пример ниже. Точно так же, как ожидается, что каждая программа Java будет иметь метод main(), ожидается, что каждый метод действия будет иметь execute()
class MyActionClass {
public static void execute() {
System.out.println("Hello from execute()!!");
}
}
public class StaticTest {
/**
* @param args
* @throws ClassNotFoundException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Class<?> clazz = Class.forName("MyActionClass");
Method method = clazz.getMethod("execute");
method.invoke(null);
}
}
Хорошо, потому что API Reflection намного медленнее, чем вызов метода, как при использовании рефлексии, компилятор вообще не может оптимизировать, поскольку он не может иметь никакого реального представления о том, что вы делаете.
Имея интерфейс и несколько конкретных классов, которые его реализуют, мы можем иметь преимущество полиморфного поведения. Добавьте шаблон Factory в уравнение, и вы можете напрямую работать с вашими интерфейсами без необходимости знать, какой конкретный метод класса вы вызываете. Дополнительным преимуществом является то, что компилятор сможет оптимизировать ваш код, заставляя его работать намного быстрее по сравнению с использованием Reflection API.
Начиная с Java 8, мы можем иметь статические и реализации методов экземпляра в интерфейсах. Вот демо:
public class InterfaceDemo
{
public static void main(String... args)
{
XYZ.executeStatic("Hello");
XYZ object = new Implementer();
object.executeInstance("Message");
}
}
interface XYZ
{
static void executeStatic(String message)
{
System.out.println("Static: " + message);
}
default void executeInstance(String message)
{
System.out.println("Instance: " + message);
}
}
class Implementer implements XYZ {}
Тогда есть функциональные интерфейсы, такие как:
@FunctionalInterface
public interface Returnable<T>
{
public T value();
}
Это позволяет создавать различные реализации с использованием лямбда-выражений, таких как:
Returnable<Integer> integerReturnable = () -> 42;
Returnable<String> stringReturnable = () -> "Hello";
И используйте как:
System.out.println(integerReturnable.value()); // Prints 42
System.out.println(stringReturnable.value()); // Prints Hello
Кстати, если есть много объектов, которые нужно создать, мы используем шаблон пула объектов или что-то подобное, и если есть много похожих объектов, мы используем шаблон Flyweight, чтобы минимизировать использование памяти, сохраняя при этом скорость.