从具有指定属性的域对象中的集合中检索对象的最佳做法是什么?
例如,我们有一个汽车保险申请,它有两个类:一个有汽车清单的人。如果我总是需要从具有指定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);
答案 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的引用,以防止客户端修改私有状态。