Java - экземпляры реализации внутри интерфейса
В моем проекте мне нужно создавать объекты для каждого вида Java Math Operator, такие как "Добавить", "Подстановка", "Умножение" и т.д. И эти операторы должны быть одноточечными.
Итак, вот что я собираюсь делать. Я определяю Math Operator как интерфейс, и я помещаю эти реализации внутри него, поскольку я не хочу определять одноэлементные классы для каждого оператора.
public interface MathOperator {
double operate(double a, double b);
MathOperator ADD = new MathOperator(){
@Override
public double operate(double a, double b) {
return a + b;
}
};
MathOperator SUBSTRACT = new MathOperator(){
@Override
public double operate(double a, double b) {
return a - b;
}
};
}
Я не вижу много такого использования, когда я это Google. Поэтому я задаюсь вопросом, является ли это хорошей практикой и есть ли более эффективные и более изящные подходы?
Ответы
Ответ 1
Я бы сделал smt like
1) Определить интерфейс
interface MathOperator {
double operate(double a, double b);
}
2) Чем некоторая общая реализация в перечислении (меньше кода)
enum MathOperators implements MathOperator {
ADD {
@Override
public double operate(double a, double b) {
return a + b;
}
},
SUBTRACT {
@Override
public double operate(double a, double b) {
return a - b;
}
}
}
3) Или публичные статические члены (более чистое решение).
class MathOperators {
public static MathOperator ADD = new MathOperator() {
@Override
public double operate(double a, double b) {
return a + b;
}
};
public static MathOperator SUBTRACT = new MathOperator() {
@Override
public double operate(double a, double b) {
return a - b;
}
};
}
- может создать новый
MathOperator
без изменения MathOperators
- иметь хороший API для общих операций
- не следует писать синглтоны
- иметь хороший чистый интерфейс
Ответ 2
Одна идиома, которую я видел в этих обстоятельствах, - это использование enum
:
public enum MathOperator {
ADD {
@Override
public double operate(double a, double b) {
return a + b;
}
},
SUBTRACT {
@Override
public double operate(double a, double b) {
return a - b;
}
};
public abstract double operate(double a, double b);
}
Ответ 3
Я часто использую этот шаблон, особенно для конкретных реализаций общих интерфейсов. Я нахожу, что это работает очень хорошо для меня.
Мне нравится, как он помещает реализации, где вы можете их найти. Я делаю это несколько иначе - я делаю их статичными (это стиль, поэтому интерфейс impls больше похож на класс impls):
public interface MathOperator {
double operate(double a, double b);
public static MathOperator ADD = new MathOperator() {
@Override
public double operate(double a, double b) {
return a + b;
}
};
public static MathOperator SUBSTRACT = new MathOperator() {
@Override
public double operate(double a, double b) {
return a - b;
}
};
}
Ответ 4
Я не вижу никаких проблем с этим. Возьмите java.lang.String.CASE_INSENSITIVE_ORDER
, например. Это почти то же самое, за исключением того, что
- Строка не является интерфейсом, а конечным классом
-
Comparator
не объявляется с использованием анонимного класса, но использует статический внутренний класс, который по сути является тем же самым
Ответ 5
Лично мне не нравится помещать реализации в интерфейсы. Я бы либо:
- make
MathOperator
a enum
- сохранить интерфейс, но factory или статический класс (скажем
MathOperators
) с реализациями
Ответ 6
Почему вы не определяете каждую реализацию в своем собственном классе/файле? Это сделает его более понятным и оставит интерфейс чистым.