前提

现有代码库(不太可能更改):

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() { ... }
}


CircleInputTriangleInputSquareInput根本不相关(不相交的类型)。

问题

输入对象可能非常复杂,我希望用户创建一个封装他们自己的业务逻辑的类。我探索了两种方法,但是它们都很笨拙,这使我不得不思考是否我错误地解决了该问题,并且有使用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
  }
}

最佳答案

因此,在此系统中,已经很好地定义了CircleSquareTriangle(均为Shape)以及它们各自的输入CircleInputSquareInputTriangleInput(不相交)。 ?

用户为什么要扩展所有这些输入?

您的管道本质上是否不是某些业务逻辑根据ShapeDependency来创建ShapeInput并将其传递给正确的Shape的管道?

您可以通过明确定义每个班级的职责来澄清这一点。我希望CircleInputSquareInput等的唯一责任是仅保存输入数据,而不执行业务逻辑。

我会将业务逻辑保留在自己的类中,也许是这样的:

abstract class BusinessLogic<S extends Shape, I> {
    private final Function<I, S> shapeConstructor;

    public BusinessLogic(Function<I, S> shapeConstructor) {
        this.shapeConstructor = shapeConstructor;
    }

    protected abstract I createShapeInput(ShapeDependency shapeDependency);

    public final S createShape(ShapeDependency shapeDependency) {
        I shapeInput = createShapeInput(shapeDependency);
        S shape = shapeConstructor.apply(shapeInput);
        return shape;
    }
}

class CircleBusinessLogic extends BusinessLogic<Circle, CircleInput> {

    public CircleBusinessLogic() {
        super(Circle::new);
    }

    @Override
    protected CircleInput createShapeInput(ShapeDependency shapeDependency) {
        return new CircleInput();
    }
}


让我知道这是否满足您的要求。如果没有,请说明您的目标和渠道。

10-04 17:19