使用数据库查找从另一种类型的对象创建一种类型的对象

时间:2019-03-27 17:54:12

标签: oop design-patterns

我有一个从第三方数据库获取汽车实体的应用程序。我称实体为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的逻辑位置似乎是构造函数。但是我对回购的需求不了解。我可以应用哪种模式,以便在构造函数中创建所有数据,但仍然不让实体知道存储库?

1 个答案:

答案 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。要实现此映射器,您可以使用DozerOrikaMapStruct或您的自定义实现。

另一个问题是如何获得ThirdPartyCar对象。如果您是通过ID的{​​{1}}加载的,则可以将抽象工厂更改为:

ThirdPartyRepository

,给定的实现负载为interface CarFactory { Car createNew(String id); } ID,并将其映射到ThirdPartyCar。一切都被工厂隐藏了,您可以轻松地进行交换。

另请参阅: