从域模型中检索集合中的项目的最佳做法是什么?

时间:2009-09-01 20:30:12

标签: java dns domain-driven-design

从具有指定属性的域对象中的集合中检索对象的最佳做法是什么?

例如,我们有一个汽车保险申请,它有两个类:一个有汽车清单的人。如果我总是需要从具有指定VIN的Person中检索Car,那么实现该方法的最佳方法是什么?我在下面提供了一些例子 - 欢迎其他人

示例1
在Person实体中添加一个新方法以检索VIN


    public class Person
    {
         private HashSet<Car> cars = new HashSet<Car>();

         public Set<Car> getCars()
         {
              return this.cars;
         }

         public Car getCarByVin(VIN vin)
         {
              //loop over cars and retrieve the car with the VIN
         }
    }

所以从一个应用程序开始,这个过程就是......


    VIN vin = new VIN(...);
    Person person = personDao.getPerson();
    Car personCar = person.getCarByVin(vin); 

示例2
在Person实体中创建一个新的列表集合,并通过VIN方法将检索添加到集合


    public class Person
    {
         private CarSet cars = new CarSet();

         public CarSet getCars()
         {
              return this.cars;
         }
    }

    public class CarSet
         implements Set<Car>
    {
         //implement required methods for Set

         public Car byVin(VIN vin)
         {
              //loop over set and retrieve the car with the VIN
         }
    }

所以从一个应用程序开始,这个过程就是......


    VIN vin = new VIN(...);
    Person person = personDao.getPerson();
    Car personCar = person.getCars().byVin(vin); 

4 个答案:

答案 0 :(得分:3)

我认为德米特定律在这里适用,这有利于第一个例子。每当你进行链接时,例如foo.getBar()。doBlah(),这就违反了得墨忒耳法则。这显然不是一个法则,但它是一个很好的指导,当一个类必须知道太多关于另一个类中的位的细节。

答案 1 :(得分:2)

一旦你说Car带有指定的VIN,你就会认为这是实体,而不是价值对象......另外,如果你需要“检索”它,暗示它是实体,而不是价值。通常不需要检索值对象,如果需要,可以动态创建一个...您确定在DDD中明确区分实体和值元素吗?

ADDED:那么如果Car是一个实体,那么从你所说的内容来看,它似乎应该是一个聚合中的成员实体,其中Person作为聚合根。 (虽然它可能是它自己的聚合的根)在任何情况下,都应该构造Person存储库,这样当你获取聚合时它也会得到那个人的汽车。 Person类应该具有Type Cars或CarCollection的属性,它被命名为Cars,或OwnedCars,或者其他什么,Type(Cars或CarCollection)应该有一个索引器,它根据VIN检索特定的Car。

public class Person    
{
   private int persId;
   // other fields
   private Cars cars;

   public Cars Cars { get; set; }
   // all other stuff
}

public class Cars: Collection<Car> // or 'public class Cars: List<Car>' or ...
{
    public bool Contains(string VinNumber]
    {
        foreach (Car c in this)
           if (c.VinNumber = VinNumber) return true;
        return false;
    }
    public Car this[string VinNumber]
    {
        get 
        {
            foreach (Car c in this)
                if (c.VinNumber = VinNumber) return c;
            return null;
        }
    }
}

答案 2 :(得分:1)

在这样的情况下,我发现将搜索方法放在对象本身上更容易,而不是尝试将集合类子类化(并带来可能由这个看似简单的决定导致的所有设计决策更改)。

以上所有假设基本设计确实是您想要的。我通常更喜欢某种外观,它允许我按人和vin搜索车辆,而不是搜索人物本身。

答案 3 :(得分:1)

我真的不喜欢你的CarSet设计。如果没有专门的行为,我不希望看到专门的课程;不可否认,这是一个证明一个观点的简单例子。

但我也反对你的Person例子。您有一个应该具有静态类型Set的HashSet的私有引用。然后你有一个getter,它返回对该私有数据成员的引用。你应该意识到这是一个任何人都可以操纵的可变引用。你的私有修饰符毫无意义。

在这种情况下,正确的做法是使用java.util.Collections类返回对不可变Set的引用,以防止客户端修改私有状态。