在我看来,这种变化与得墨忒耳定律没有任何关系。从本质上讲,该定律是关于通过将方法调用整个其他对象链,将对象图的结构编码到代码中。例如,假设在汽车保险应用程序中,客户有一个保单,一个保单有车辆,车辆有司机分配给他们,司机有出生日期,因此有年龄。您可以想象以下代码:
public boolean hasUnderageDrivers(Customer customer) {
for (Vehicle vehicle : customer.getPolicy().getVehicles()) {
for (Driver driver : vehicle.getDrivers()) {
if (driver.getAge() < 18) {
return true;
}
}
}
return false;
}
这将违反德米特定律,因为该代码现在具有不需要知道的内部知识。它知道司机被分配到车辆,而不仅仅是被分配到整个保险单。如果将来保险公司决定司机只是在保单上,而不是被分配到特定的车辆,那么这个代码将不得不改变。
问题在于,它调用其参数的一个方法,然后调用另一个、然后另一个、 、 然后是另一个。德米特定律说,一个类的方法应该只在以下方面调用方法:getPolicy()
getVehicles()
getDrivers()
getAge()
(最后一个可能是单元测试的问题,你可能希望由工厂注入或创建对象,而不是直接在本地创建,但这与Demeter定律无关。
要解决此问题,我们可以传入对象,并且可以有一个知道如何确定策略是否具有未成年驱动程序的方法:hasUnderageDrivers()
Policy
Policy
public boolean hasUnderageDrivers(Policy policy) {
return policy.hasUnderageDrivers();
}
把一个级别调低,可能是可以的——得墨忒耳定律是一个经验法则,而不是一个硬性规定。您可能也不必担心不太可能改变的事情; 可能总是会继续有一个出生日期和一种方法。customer.getPolicy().hasUnderageDrivers()
Driver
getAge()
但是回到你的案例,如果我们用公共领域取代所有这些获取者会发生什么?它对得墨忒耳定律毫无帮助。您仍然可能遇到与第一个示例中完全相同的问题。考虑:
public boolean hasUnderageDrivers(Customer customer) {
for (Vehicle vehicle : customer.policy.vehicles) {
for (Driver driver : vehicle.drivers) {
if (driver.age < 18) {
return true;
}
}
}
return false;
}
(我甚至已经转换为 ,尽管这可能是基于出生日期的计算,而不是简单的字段。driver.getAge()
driver.age
请注意,当我们使用公共字段而不是 getters 编写代码时,存在嵌入对象图如何组合在一起的知识(客户有一个策略,其中包含具有驱动程序的车辆)的完全相同的问题。问题与这些碎片如何组合在一起有关,而不是与是否被调用了getter有关。
顺便说一句,更喜欢getter而不是(最终的?)公共字段的正常原因是,你以后可能需要在它们后面放一些逻辑。年龄被替换为基于出生日期和今天日期的计算,或者设置者需要有一些与之关联的验证(例如,如果您通过,则抛出)。我以前没有听说过德墨忒耳定律在这种背景下被引用。null