Java 设计通讯簿最面向对象的方法是什么?

Java 设计通讯簿最面向对象的方法是什么?,java,design-patterns,class-design,Java,Design Patterns,Class Design,我在问自己如何用Java设计一个面向对象的通讯簿 比如说,一个联系人可以有几个联系人详细信息,比如地址、电话号码和电子邮件地址 实现这一点的一种方法是为每种类型的联系人提供一个ArrayList。但必须有一个更好、更面向对象的解决方案。这是什么?我不认为这是特别不面向对象的。如果您的域是这样的,一个人可以有零个或多个电子邮件地址,那么您几乎准确地描述了使用列表的情况 我能想到的唯一替代方法是在 WorkEmail PersonalEmail OtherEmail1 OtherEmail2 Oth

我在问自己如何用Java设计一个面向对象的通讯簿

比如说,一个联系人可以有几个联系人详细信息,比如地址、电话号码和电子邮件地址


实现这一点的一种方法是为每种类型的联系人提供一个ArrayList。但必须有一个更好、更面向对象的解决方案。这是什么?

我不认为这是特别不面向对象的。如果您的域是这样的,一个人可以有零个或多个电子邮件地址,那么您几乎准确地描述了使用列表的情况

我能想到的唯一替代方法是在

WorkEmail
PersonalEmail
OtherEmail1
OtherEmail2
OtherEmail3
但我认为这更糟,因为:

您不能支持超过五个电子邮件地址。您可以添加更多字段,但这会增加后几点的痛苦,并且仍然会施加一些有限的限制。 你暗示了一些可能存在的额外语义,如果相同的地址用于工作和个人用途呢?如果两者都不适用,你能填上其他的吗?如果你不知道目的呢? 您现在必须手动测试每个字段,以查看哪个字段为空,这将涉及Java中大量的重复。你不能使用像增强for循环这样的好功能来对每个电子邮件地址应用相同的块,也不能简单地计算有多少个地址 一个人拥有的财产清单现在不那么干净了。我想您可以将这些属性打包到EmailContactDetails类或其他什么东西中,但现在您有了一个额外的间接层次,即概念上的复杂性,而没有真正的好处。
因此,如果一个人的电子邮件地址列表可能是空的,没有边界,那么将其表示为一个列表有什么错呢?

你的思路是对的。我唯一不同的做法是使用而不是ArrayList集合来引用contacts的属性集合。这是基于中所述的代码到接口经验法则和其他许多规则的建议。

您也可以使用,然后通过myMap.GetEmailAddress1获取特定值,或者像通过myMap.entrySet使用列表一样遍历整个地图。

我能给你的最有用的OOP建议是为每一条信息创建一个类。例如:

public abstract class ContactInfo { /* ... */ }

public class Address extends ContactInfo { /* ... */ }

public class PhoneNumber extends ContactInfo { /* ... */ }

public class EmailAddress extends ContactInfo { /* ... */ }

public class Contact {
    private String name;
    private Set<ContactInfo> info;
    // ...
}
最后

public class AddressBook {
    List<Contact> contacts;
    // ...
}

对于你的具体案例来说,这可能是过分的,也可能不是过分的,但作为一个思想实验,这是一条路要走。它显然负责OOP的文字部分——使用对象——但也为封装、抽象和继承奠定了基础,这些都是密切相关的原则。

处理大多数用例的一种简单方法就是这样

public class AddressBook {
    private Map<String, Contact> contacts;
    
    AddressBook(){
        contacts = new HashMap<String, Contact>();
    }
    
    public boolean addContact(Contact contact) {
        if(contacts.containsKey(contact.getName())) {
            System.out.println("Already exists");
            return false;
        }
        contacts.put(contact.getName(), contact);
        return true;
    }

    public boolean updateContact(Contact contact) {
        contacts.put(contact.getName(), contact);
        return true;
    }
}

class Contact{
    private String name;
    private String email;
    private String phone;
    private Address address;
    
    public Contact(String name) {
        this.name = name;
    }
    
    public Contact(String name, String email, String phone, Address address) {
        this.name = name;
        this.email = email;
        this.phone = phone;
        this.address = address;
    }

    // getters and setters
    
    @Override
    public String toString() {
        return "name is "+name+" and address is "+address;
    }
}

class Address{
    private String street1;
    private String street2;
    private String city;
    private int zipcode;
    
    public Address() {}

    // getters and setters
    
    @Override
    public String toString() {
        return "street1 is "+street1+" and zipcode is "+zipcode;
    }
}

谢谢你的回答。但是我如何确定联系人条目是哪种类型呢?@Mark,你不会的,我在这里提供了确切的代码。在任何真正的程序中,您都必须进行一些裁剪以满足您的独特需求。如果您需要立即了解类型,请设置地址;设置电话号码;也许是个好办法。我假设您指的是信息条目而不是联系人条目。添加一些有用的说明以帮助有疑问的人。仅仅删除一段代码并没有多大帮助。