What's the most object-oriented way to design an address book?
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?
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.
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.
I don't think that's particularly un-object oriented. If your domain is such that a Person
can have zero or more EmailAddress
es, 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 anEmailContactDetails
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?
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()
.
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;
}
}
精彩评论