我有一个从第三方数据库获取汽车实体的应用程序。我称实体为ThirdPartyCar
。我的应用程序需要通过使用Car
中的数据来创建ThirdPartyCar
实体。但是,Car
实体还必须从我的应用程序的数据库中获取其某些数据。例如,状态ThirdPartyCar
可能是_BOUGHT
,并且通过数据库查找,我的应用程序必须转换为Sold
。
我目前有一个Car
自变量的ThirdPartyCar
构造函数。但是Car
构造函数无法填充查找数据,因为它是一个实体,并且实体不应引用存储库。因此,我还有一项服务来填充剩余数据:
public class ThirdPartyCar {
@Id
private Long id;
private String vin;
private String status;
// more props + default constructor
}
public class Car {
@Id
private Long id;
private String vin;
private CarStatus status;
// more props (some different than ThirdPartyCar) + default constructor
public Car(ThirdPartyCar thirdPartyCar) {
this.vin = thirdPartyCar.getVin();
// more props set based on thirdPartyCar
// but props leveraging database not set here
}
public class CarStatus {
@Id
private Long id;
private String status;
}
public class CarBuilderService {
private final CarStatusMappingRepository repo;
public Car buildFrom(ThirdPartyCar thirdPartyCar) {
Car car = new Car(thirdPartyCar);
CarStatus status = repo.findByThirdPartyCarStatus(thirdPartyCar.getStatus());
car.setStatus(status);
// set other props (including nested props) that depend on repos
}
}
基于Car
创建ThirdPartyCar
的逻辑位置似乎是构造函数。但是我对回购的需求不了解。我可以应用哪种模式,以便在构造函数中创建所有数据,但仍然不让实体知道存储库?
答案 0 :(得分:1)
您应避免链接来自POJO
中不同域的两个constructor
类。这两个类不应该相互了解。也许它们在两个不同的系统中代表相同的概念,但是它们并不相同。
好的方法是创建Abstract Factory
界面,该界面将在应从Car
创建ThirdPartyCar
的任何地方使用:
interface ThirdPartyCarFactory {
Car createNewBasedOn(ThirdPartyCar source);
}
一个实现可能是您的RepositoryThirdPartyCarFactory
:
class RepositoryThirdPartyCarFactory implements ThirdPartyCarFactory {
private CarStatusMappingRepository repo;
private CarMapper carMapper;
public Car createNewBasedOn(ThirdPartyCar thirdPartyCar) {
Car car = new Car();
carMapper.map(thirdPartyCar, car);
CarStatus status = repo.findByThirdPartyCarStatus(thirdPartyCar.getStatus());
car.setStatus(status);
// set other props (including nested props) that depend on repos
return car;
}
}
在上述实现中,您可以找到CarMapper
,它知道如何将ThirdPartyCar
映射到Car
。要实现此映射器,您可以使用Dozer,Orika,MapStruct或您的自定义实现。
另一个问题是如何获得ThirdPartyCar
对象。如果您是通过ID
的{{1}}加载的,则可以将抽象工厂更改为:
ThirdPartyRepository
,给定的实现负载为interface CarFactory {
Car createNew(String id);
}
ID
,并将其映射到ThirdPartyCar
。一切都被工厂隐藏了,您可以轻松地进行交换。
另请参阅: