设计通讯录的最面向对象方式是什么?

时间:2011-03-22 15:49:29

标签: java design-patterns class-design

我问自己如何用Java设计面向对象的地址簿。

假设联系人可以有多个联系方式,如地址,电话号码和电子邮件地址。

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

5 个答案:

答案 0 :(得分:2)

你走在正确的轨道上。我唯一不同的做法是使用List interface而不是ArrayList集合来引用联系人的属性集合。这是基于代码到接口的经验法则的建议,如this article和许多其他人所述。

答案 1 :(得分:2)

我能给你的最多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的文字部分 - 使用对象 - 但也为封装,抽象和继承奠定了基础,这些是密切相关的原则。

答案 2 :(得分:1)

我认为这不是特别是非面向对象的。如果您的域名Person可以包含零个或多个EmailAddress,那么您几乎已经准确地描述了使用列表的情况。

我能想到的唯一替代方法是拥有诸如

之类的字段
WorkEmail
PersonalEmail
OtherEmail1
OtherEmail2
OtherEmail3

但在我看来情况更糟,因为:

  • 您根本无法支持超过五个电子邮件地址(嗯,您可以添加更多字段,但这会增加后一点的痛苦,但仍会施加一些限制。)
  • 你暗示一些额外的语义而不是可能出现的(如果同一地址用于工作和个人怎么办?如果两者都不适用,你可以填写Other吗?如果不这样做怎么办?知道目的吗?)
  • 您现在必须手动测试每个字段以查看哪个为空,这将涉及Java中的非常重要的重复数量。您不能使用增强型for循环之类的好功能将相同的块应用于每个电子邮件地址,并且您无法轻易计算有多少地址
  • Person所拥有的属性列表现在更不干净了。我想你可以将这些属性打包成EmailContactDetails类或者其他东西,但是现在你有一个额外的间接层次(更多的概念复杂性),没有真正的收获。

因此,如果一个人有一个可能空的,无限制的电子邮件地址列表,那么将其表示为列表有什么问题?

答案 3 :(得分:0)

您还可以使用Map,然后获取具体值,例如通过myMap.get("emailAdress1")或迭代整个地图,就像通过myMap.entrySet()列表一样。

答案 4 :(得分:0)

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

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;
    }
}