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

发布于 2024-10-25 11:21:59 字数 143 浏览 2 评论 0原文

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

假设联系人可以有多个联系详细信息,例如地址、电话号码和电子邮件地址。

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

I am asking myself how to design an object-oriented address book in Java.

Let's say a contact can have several contact details, like addresses, phone numbers and e-mail addresses.

One way to implement this would be to give every contact an ArrayList for every type. But there must be a better and more object-oriented solution. What is it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

第几種人 2024-11-01 11:21:59

我能给你的最面向对象的建议是为每个项目/信息创建一个类。例如:

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 的字面部分——使用对象——但也为封装、抽象和继承奠定了基础,这些都是密切相关的原则。

The most OOP suggestion I can give you is to create a class for every item/piece of information. For example:

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

and finally,

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

This may or may not be overkill for your specific case, but as a thought experiment, it's the way to go. It obviously takes care of the literal part of OOP — using objects — but also lays groundwork for encapsulation, abstraction and inheritance, which are closely related principles.

老子叫无熙 2024-11-01 11:21:59

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

You're on the right track. The only thing I would do differently would be to use a List interface instead of an ArrayList collection to reference the contacts' attribute collections. This is advice based on the code-to-interfaces rule-of-thumb as described in this article and many others.

分開簡單 2024-11-01 11:21:59

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

我能想到的唯一替代方法是使用诸如此类的字段,

WorkEmail
PersonalEmail
OtherEmail1
OtherEmail2
OtherEmail3

但在我看来,这更糟糕,因为:

  • 您根本无法支持超过五个电子邮件地址(好吧,您可以添加更多字段,但这会增加后者的痛苦点并且仍然施加一些有限的限制。)
  • 您暗示了一些可能存在的额外语义(如果相同的地址用于工作和个人怎么办?如果两者都不适用怎么办,您可以只填写其他 如果您不知道目的怎么办?)
  • 您现在必须手动测试每个字段以查看哪些字段为空,这将涉及 Java 中大量的重复。您无法使用增强型 for 循环等优秀功能将相同的块应用于每个电子邮件地址,并且您无法简单地计算有多少个地址
  • Person 拥有的属性列表现在不太干净了。我想您可以将这些属性打包到 EmailContactDetails 类或其他内容中,但现在您获得了额外的间接级别(概念更复杂),但没有真正的好处。

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

I don't think that's particularly un-object oriented. If your domain is such that a Person can have zero or more EmailAddresses, then you've almost exactly described the situation to use a list.

The only alternative approach I can think of would be to have fields such as

WorkEmail
PersonalEmail
OtherEmail1
OtherEmail2
OtherEmail3

but in my opinion that's worse, because:

  • You simply cannot support more than five email addresses (well, you could add more fields, but that increases the pain of the latter points and still imposes some finite limit.)
  • You're implying some extra semantics than may be present (what if the same address is used for work and personal? What if neither applies, can you just fill the Other ones? What if you don't know the purpose?)
  • You now have to test each field manually to see which is null, which is going to involve a non-trivial amount of duplication in Java. You can't use nice features like the enhanced-for loop to apply the same block to every email address, and you can't trivially count how many addresses there are
  • The list of properties that a Person has is now much less clean. I suppose you could package these properties into an EmailContactDetails class or something, but now you've got an extra level of indirection (more conceptual complexity) for no real gain.

So, if a person has a possibly-empty, unbounded list of email addresses, what's wrong with representing that as a list?

骑趴 2024-11-01 11:21:59

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

You can also use a Map, and then get specific values e.g. via myMap.get("emailAdress1") or iterate over the whole map like you would do with a list via myMap.entrySet().

┾廆蒐ゝ 2024-11-01 11:21:59

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

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

One simple way to handle most of the use cases can be like this

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文