gpt4 book ai didi

java - 得墨忒耳法则与集合组合如何协同工作?

转载 作者:搜寻专家 更新时间:2023-10-30 21:12:41 25 4
gpt4 key购买 nike

我几乎阅读了所有标有 Demeter 法则的问题。我的具体问题在其他任何问题中都没有得到回答,尽管它非常相似。我的主要问题是,当您有一个具有多层组合的对象,但需要从各种对象中检索属性值时,您如何实现这一点,为什么要采用一种方法而不是另一种方法?

假设您有一个由其他对象组成的非常标准的对象,如下所示:

public class Customer {
private String name;
private ContactInfo primaryAddress;
private ContactInfo workAddress;
private Interests hobbies;
//Etc...

public getPrimaryAddress() { return primaryAddress; }
public getWorkAddress() { return workAddress; }
public getHobbies() { return hobbies; }
//Etc...
}

private ContactInfo {
private String phoneNumber;
private String emailAddress;
//Etc...

public getPhoneNumber() { return phoneNumber; }
public getEmailAddress() { return emailAddress; }
//Etc...
}

private Interests {
private List listOfInterests;
}

以下都违反得墨忒耳法则:

System.out.println("Phone: " + customer.getPrimaryAddress().getPhoneNumber());
System.out.println("Hobbies: " + customer.getHobbies().getListOfInterests().toString());

我认为这也违反了 Demeter 法则(澄清?):

ContactInfo customerPrimaryAddress = customer.getPrimaryAddress();
System.out.println("Phone: " + customerPrimaryAddress.getPhoneNumber());

因此,您可能会向 Customer 添加一个“getPrimaryPhoneNumber()”方法:

public getPrimaryPhoneNumber() {
return primaryAddress.getPhoneNumber();
}

然后只需调用: System.out.println("电话:"+ customer.getPrimaryPhoneNumber());

但随着时间的推移这样做似乎实际上会带来很多问题并且违背 Demeter 法则的意图。它使 Customer 类成为一个巨大的 getter 和 setter 包,对它自己的内部类有太多的了解。例如,Customer 对象似乎有朝一日可能会有不同的地址(不仅仅是“主要”地址和“工作”地址)。甚至 Customer 类也可能只有 ContactInfo 对象的列表(或其他集合),而不是特定的命名 ContactInfo 对象。在那种情况下,您如何继续遵循得墨忒耳法则?这似乎违背了抽象的目的。例如,在客户拥有 ContactInfo 项目列表的情况下,这似乎是合理的:

Customer.getSomeParticularAddress(addressType).getPhoneNumber();

当您想到某些人拥有手机和固定电话时,这似乎会变得更加疯狂,然后 ContactInfo 必须有电话号码的集合。

Customer.getSomeParticularAddress(addressType).getSomePhoneNumber(phoneType).getPhoneNumber();

在这种情况下,我们不仅在对象中引用对象中的对象,而且还必须知道有效的 addressType 和 phoneType 是什么。我绝对可以看出这个问题,但我不确定如何避免它。特别是当任何类(class)打电话时,可能确实知道他们想要为相关客户的“主要”地址提取“移动”电话号码。

如何重构它以符合 Demeter 法则,为什么这样会好?

最佳答案

根据我的经验,显示的 Customer 示例不是“由其他对象组成的标准对象”,因为该示例采取了额外的步骤将其组成部分实现为内部类,并进一步使这些内部类私有(private)。这不是坏事。

一般来说,private 访问修饰符增加了信息隐藏,这是 Demeter 法则的基础。暴露私有(private)类是矛盾的。 NetBeans IDE 实际上包括一个默认的编译器警告,“通过公共(public) API 导出非公共(public)类型”。

我会断言,将私有(private)类暴露在其封闭类之外总是不好的:它会减少信息隐藏并违反 Demeter 法则。因此,要回答有关在 Customer 之外返回 ContactInfo 实例的澄清问题:是的,这是违规行为。

getPrimaryPhoneNumber() 方法添加到 Customer 的建议解决方案是一个有效的选项。困惑就在这里:“客户……对其内部类的了解太多了。”那是不可能的;这就是为什么这个示例不是标准组合示例很重要的原因。

封闭类对任何嵌套类有 100% 的了解。总是。无论这些嵌套类如何在封闭类(或其他任何地方)中使用。这就是为什么封闭类可以直接访问其嵌套类的私有(private)字段和方法的原因:封闭类天生就知道它们的一切,因为它们是在它内部实现的。

给出类 Foo 的荒谬示例,它有一个嵌套类 Bar,它有一个嵌套类 Baz,它有一个嵌套类 Qux,Foo(内部)调用 bar 不会违反 Demeter。 baz.qux.方法()。 Foo 已经知道关于 Bar、Baz 和 Qux 的一切;因为他们的代码在 Foo 中,所以没有额外的知识通过长方法链传递。

然后,根据 Demeter 法则,Customer 的解决方案是不返回中间对象,无论其内部实现如何;即,无论 Customer 是使用多个嵌套类还是不使用嵌套类实现的,它都应该只返回其客户端类最终需要的内容。

例如,最后一个代码片段可能被重构为,customer.getPhoneNumber(addressType, phoneType);

或者如果只有少数选项,customer.getPrimaryMobilePhoneNumber();

这两种方法都会导致 Customer 类的用户不知道其内部实现,并确保这些用户不必调用他们不直接感兴趣的对象。

关于java - 得墨忒耳法则与集合组合如何协同工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15692448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com