Предпосылка
Существующая кодовая база (вряд ли изменится):
public interface Shape {
void print();
}
И с реализациями, такими как (Круг, Треугольник, Квадрат и т. Д.):
public final class Circle implements Shape {
private final CircleInput input;
public Circle(CircleInput input) {
this.input = input;
}
@Override
public void print() { ... }
}
CircleInput
, TriangleInput
и SquareInput
НЕ связаны вообще (непересекающиеся типы).
Задача
Входные объекты могут быть очень сложными, и я хочу, чтобы пользователи создали класс, который инкапсулирует их собственную бизнес-логику. Я исследовал два подхода, но оба они были неуклюжими, и это наводит меня на мысль, неправильно ли я подхожу к проблемеи есть лучший способ использовать Java.
Вариант 1
Я думал об определении универсального интерфейса:
public interface ShapeInput<T> {
T getInput();
}
Пользователь может затемсоздать:
public final class MyCircleInput<CircleInput> {
private final ShapeDependency shapeDependency;
@Inject
MyCircleInput(ShapeDependency shapeDependency) {
this.shapeDependency = shapeDependency;
}
@Override
public CircleInput getInput() {
return createCircleInput(shapeDependency);
}
// ... very complex business logic ...
private static CircleInput createCircleInput(
ShapeDependency shapeDependency) {
// returns a CircleInput
}
}
, а затем использовать ShapeFactory для создания правильного экземпляра на основе типа. Но я не могу сказать ShapeInput<CircleInput | TriangleInput>
, и для принудительного выполнения этого поведения требуются проверки во время выполнения.
Опция 2
Я мог бы использовать наследование на Shape
напрямую:
public abstract class AbstractShape implements Shape {
protected final Shape shapeImpl;
public AbstractShape(CircleInput input) {
this.shapeImpl = new Circle(input);
}
public AbstractShape(TriangleInput input) {
this.shapeImpl = new Triangle(input);
}
// Proxies print() to the underlying impl.
@Override
public void print() {
return shapeImpl.print();
}
}
и пользователи могут создавать:
public final MyCircle extends AbstractShape {
@Inject
MyCircle(ShapeDependency shapeDependency) {
super(createCircleInput(shapeDependency));
}
// ... very complex business logic ...
private static CircleInput createCircleInput(
ShapeDependency shapeDependency) {
// returns a CircleInput
}
}