从数据库中检索其属性的简单类型的创建模式

本文关键字:简单 类型 创建 模式 属性 数据库 检索 | 更新日期: 2023-09-27 18:01:21

背景

为了我自己的理解,我正在尝试为一个简单的场景创建一个分层体系结构。 我有一个简单的域类,汽车。 

public class Car {
  public string Make;
  public string Model;
  public int Year;
  public Accelerate() { }
  public Decelerate() { }
}

我想创建一个新的 Car 实例,从数据库中填充其值。 这就是我卡住的地方。

我认为持久性层(称为CarRepository(中应该有另一个类,它将完成从基于CarID的数据库中检索这些值的肮脏工作。

我希望在运行时将此 CarRepository 依赖项注入到 Car 域类中,以允许不同的实现(例如用于单元测试的假货(。

因此,我考虑将其添加到 Car 类中:

public class Car() {
  private ICarRespository _carRepository;
  public Car(ICarRepository carRepository) {
    _carRespository = carRepository;
  }
  public void Find(int carId) {
    var car = _carRepository.FindById(carId);
    this.Make = car.Make;
    this.Model = car.Model;
    // etc.
  }
  // other properties and methods here
}

我将ICarRepository定义为:

public interface ICarRepository {
  DtoCar FindById(int carId);
}
public class DtoCar {
  public string Make;
  public string Model;
  public int Year;
}

假设我正在使用"穷人的依赖注入",并允许聚合根根据项目类型(生产代码与单元测试(通过正确的具体 CarRespository。 显然,我选择在这里使用构造函数注入。

问题

(1(这个解决方案感觉不对。 当我创建一辆新车时,我觉得它应该在那个时候初始化,并填充它的所有属性。 但是,只有在我调用 Find(( 方法之后,它才能真正成为一辆有效的汽车。 如果我没有传递有效的 CarID 进行查找,会发生什么情况? 那么 Car 对象将永远不会是有效对象! 这不应该打扰我吗? 有没有更好的方法?

(2(我正在使用构造函数注入来传递存储库依赖项...我也可以传递 CarID 以在构造函数中找到这里吗......然后我可以消除 Find(( 方法吗? 所以:

public Car(ICarRepository carRepository, int carId) {
  _carRespository = carRepository;
  var car = _carRepository.FindById(carId);
  this.Make = car.Make;
  this.Model = car.Model;
  // etc.
}

。我从未见过这样做,所以我对使用它犹豫不决。 这样做可以吗?

(3(我在这里缺少一些创造模式吗? 这是一个简单的场景...我不相信像工厂,单例或原型这样的东西在这里适用(我可能弄错了(。 那些感觉沉重而专业。 此方案(来自数据库的简单域对象(似乎非常基本,必须提供一些指导。

从数据库中检索其属性的简单类型的创建模式

你的问题是你没有遵循单一责任原则。您应该将汽车的创建卸载到专门从事此的服务。

class CarService
{
    CarService(ICarRepository carRepo)
    { 
        _carRepo = carRepo;
    }
    Car GetById(int id)
    {
        var carDTO = _carRepo.GetById(id);       
        var car = Mapper.Map<CarDTO, Car>(carDTO);
        return car;
    }
}

*这是自动映射器的链接

**你甚至不需要CarDTO,但是如果需要,它会添加一个抽象层。

这将像工厂一样运行,但实现更有意义,并且不像您担心的那样繁重。代码将读得更像这样:

var car = carService.GetById(id);

我相信,这应该可以解决你所有的问题。

Car类的设计违反了单一责任原则:它是一个域实体,它包含数据持久性逻辑。

因此,让我们Car只是一个域实体(ID属性已被引入(:

public class Car
{
    public Car(int id, string make, string model, int year)
    {
        ID = id;
        Make = make;
        Model = model;
        Year = year;
    }
    public int ID { get; private set; }
    public string Make { get; private set; }
    public string Model { get; private set; }
    public int Year { get; private set; }
    public void Accelerate() { }
    public void Decelerate() { }
}

存储库接口不得返回数据传输对象:

public interface ICarRepository
{
    Car FindById(int carId); // No DTO here - DTO is the detail of implementation
}

然后,只需设计汽车服务的界面。服务层公开业务逻辑。在这个简单的情况下,服务层不增加任何值:

public interface ICarService
{
    Car FindById(int carId);
}
public class CarService : ICarService
{
    private readonly ICarRepository _repository;
    public CarService(ICarRepository repository)
    {
        _repository = repository;
    }
    #region Implementation of ICarService
    public Car FindById(int carId)
    {
        var car = _repository.FindById(carId);
        // The additional business logic (if required) could be added here.
        return car;
    }
    #endregion
}

存储库的实际实现将使用其构造函数创建Car