繁体   English   中英

根据外部调用构造域对象的最佳实践是什么?

[英]What is the best practice to construct a Domain Object depending on external calls?

我正在尝试构建一个从外部 API 获取其数据的对象。 我将尝试用一个例子来解释它:

首先,我在我的 API 中获得一个 POST 正文来创建一个对象:

class CarRequestBody {
    private String colorId;
    private String engineId;
    //Constructors, etc.
}

然后有了这些信息,我需要构建 Car 的详细实例。 从外部服务提供数据:

ColorDetails color = colorApiClient.getColor(colorId);
EngineSpecifications engine = engineApiClient.getEngine(engineId);

最后,我用所有这些信息构建了我的域对象。

所以我想知道构建实例的最佳实践是什么。 我以3种不同的方式思考过:

1 - CarService 中的方法如下:

public Car createCar(CartRequestBody body) {
    ColorDetails color = colorApiClient.getColor(body.getColorId);
    EngineSpecifications engine = engineApiClient.getEngine(body.getEngineId);
    Car car = new Car(color, engine);
} 

2 - 在构造函数中输入数据:

public Car(CarRequestBody body) {
    this.color = colorApiClient.getColor(body.getColorId);
    this.engine = engineApiClient.getEngine(body.getEngineId);
}

3 - 在域类的吸气剂中:

class Car {
    private ColorData color;
    private EngineSpecifications engine;
    //Constructor

    public ColorData getColor() {
        if (color == null){
            return colorApiClient.getColor(colorId);
        }
        return this.color;
    }
    ....
}

这种情况有一些设计模式吗?

我建议使用Builder设计模式。

在这里你可以看到代码 -

汽车.java

 public class Car{   
   private ColorDetails colorDetails;
   private EngineSpecifications specifications;

  private Car(CarBuilder builder){
      this.colorDetails = builder.colorDetails;
      this.specifications = builder.specifications;
  }

  public static class CarBuilder {

      private ColorDetails colorDetails;
      private EngineSpecifications specifications;

      public CarBuilder withColor(ColorDetails colorDetails) {
        this.colorDetails = colorDetails;
        return this;
    }
     public CarBuilder withSpecifications(EngineSpecifications 
          specifications) {
        this.specifications = specifications;
        return this;
    }
    
   public Car build() {
        Car car = new Car(this);
        return car;
       }
   }
 }

// 客户端代码

 public class Client{

  ColorDetails color = colorApiClient.getColor(colorId);
  EngineSpecifications engine = engineApiClient.getEngine(engineId);
 Car car = new Car.CarBuilder()
          .withColor(color)
          .withSpecifications(engine)
          .build();
   }

如果你的目标是保持你的设计干净,你的域类Car应该只知道它需要正常运行的对象,如ColorDataEngineSpecificationsonly

apiClient注入Car类不是一个好主意,因为它与它的功能无关,并且会增加耦合

此外,如果 API 调用失败怎么办,您真的想将处理这种情况的管道代码添加到构造函数中吗?

同样,我看不出定义一个期望CarRequestBody的构造函数有什么好处。

最简洁的方法是让域类的构造函数保持简单,并且不受不需要它们执行的对象的影响。 如果你想概括这些领域类的实例化过程,你可以引入实用方法来处理它。

一个简单的构造函数会有什么问题? 我不知道 Java,但在 C# 中是这样的:

class Car {
   ...
    public Car(Color color, Engine engine) {
   ... // set properties with the parameters
   }
}

哦,如果你想做一些解耦,请不要在你的域中使用与 API 中相同的对象。 所以你需要某种 Mapper 对象。

// 编辑

由于您使用的是请求,因此您可以创建一个 requesthandler 类。 如果您使用控制反转或调解器,您可以通过这种方式将请求连接到处理程序。 所以你可以研究那些设计模式。 您还可以查看 Clean Architecture 以将您的域代码与外部系统(在这种情况下为 API)分离

public CarRequestHandler : IRequestHandler<CarRequest> {
    public CarRequestHandler(IColorRepository colorRepository, IEngineRepository engineRepository) { 
this.colorRepo = colorRepository; //etc.}
    public Handle(CarRequest request) {
// call repositories with the ids and create the domain object and stuff
       
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM