1

背景

根据我自己的理解,我正在尝试为一个简单的场景创建一个分层架构。我有一个简单的域类 Car。  

public class Car {

  public string Make;
  public string Model;
  public int Year;

  public Accelerate() { }
  public Decelerate() { }
}

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

认为在 Persistence 层(称为 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 传递给 Find,会发生什么?那么 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)我在这里缺少一些创造模式吗?这是一个简单的场景……我不相信像 Factory、Singleton 或 Prototype 这样的东西在这里适用(我可能弄错了)。那些感觉沉重和专业。这个场景——来自数据库的一个简单的域对象——看起来很基本,必须有一些指导。

4

2 回答 2

4

您的问题是您没有遵循单一职责原则。您应该将汽车的创建工作交给专门从事此工作的服务。

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;
    }
}

*这里是AutoMapper的链接

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

这将像一个工厂,但实施更有意义,并不像你担心的那样沉重。代码将更像这样:

var car = carService.GetById(id);

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

于 2013-02-27T18:47:38.397 回答
3

类的设计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
}

然后,只需设计 Car服务的接口即可。服务层暴露业务逻辑。在这个简单的例子中,服务层没有增加任何价值:

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使用其构造函数创建。

于 2013-02-27T18:57:24.403 回答