Here is the problem:
Suppose I have a huge collection of Person object, and I need to traverse the list in different ways. For example, iterate a list of people born in 1980, or live in New York City. Write down the code using ITERATOR pattern to iterate over people born in a particular year. Note that the code MUST be easy to modify or extend so that different criteria can be used.
First I used builder pattern for Person class.
public class Person {
//mandatory
private final String SSN; //social security number
private final MyDate DOB; //date of birth
private String name; //name
//optional
private String phone; //phone number
private USAddress address; //home address
private USAddress workAddress; //work address
private Set<USAddress> FVA; //frequently visited addresses
private Set<Person> familyMembers; //family members
private Person(PersonBuilder builder){
...
}
Secondly the container class for Person.
public class PersonList extends ArrayList<Person> {
public PersonList() {
super();
}
//our list only stores unique elements
@Override
public boolean add(Person person) {
return !this.contains(person) && super.add(person);
}
//person iterator
public PersonIterator personIterator() {
return new PersonIterator(this);
}
}
Finally my way to implement the iterator pattern.
public class PersonIterator implements Iterator<Person> {
private int index;
private Mode mode; //iteration mode
private List<Person> origin; //ref to the input list
private List<Person> temp; //used to store sublist
//iteration mode
private enum Mode {
NORMAL,
YEAR,
CITY
}
//constructor, the default mode is normal
public PersonIterator(PersonList list){
mode = Mode.NORMAL;
index = 0;
origin = list;
temp = new ArrayList<>();
}
//set to normal mode
public void normalMode(){
index = 0;
mode = Mode.NORMAL;
}
//set to year mode
public void yearMode(int year){
index = 0;
mode = Mode.YEAR;
temp.clear();
for(Person p: origin){
if(p.getDOB().getYear() == year){
temp.add(p);
}
}
}
//set to city mode
public void cityMode(String city){
index = 0;
mode = Mode.CITY;
temp.clear();
for(Person p: origin){
if(p.getAddress().getCity().equals(city)){
temp.add(p);
}
}
}
//
@Override
public boolean hasNext() {
if(mode == Mode.NORMAL){
return index < origin.size();
}
else{
return index < temp.size();
}
}
@Override
public Person next() {
if(mode == Mode.NORMAL){
if(!this.hasNext()){
throw new NoSuchElementException();
}
Person p = origin.get(index);
index++;
return p;
}
else{
if(!this.hasNext()){
throw new NoSuchElementException();
}
Person p = temp.get(index);
index++;
return p;
}
}
}
It has several iteration mode for different criteria. The normal mode just traverses through the list, nothing more. The other mode, year mode for instance, adds all perons who were born in that year into the temp sublist, and then traverses this temp sublist normally.
To add more mode:
-
create a mode in enum
-
create a "xMode" method, and define how to fill the temp sublist
I tested the implamentation.
public static void main(String[] args) {
Person john = new Person.PersonBuilder("110", 1980, 8, 2, "john")
.phone("120")
.address("1000", "5th", "ave", "11F", "New York", "NY", 11345)
.workAddress()
.addFVA(null)
.addFamilyMember(null)
.build();
Person adam = new Person.PersonBuilder("120", 1980, 11, 22, "adam")
.phone("130")
.address("31", "main", "st", "", "Stony Brook", "NY", 11411)
.workAddress()
.addFVA(null)
.addFamilyMember(null)
.build();
Person lucy = new Person.PersonBuilder("130", 1978, 1, 3, "lucy")
.phone("140")
.address("1200", "6th", "ave", "2A", "New York", "NY", 11346)
.workAddress()
.addFVA(null)
.addFamilyMember(null)
.build();
PersonList list = new PersonList();
list.add(john);
list.add(adam);
list.add(lucy);
PersonIterator i = list.personIterator();
//normal iterator
while(i.hasNext()){
System.out.println(i.next().getName() + " is in the list");
}
//year mode, print out persons who were born in 1980
i.yearMode(1980);
while(i.hasNext()){
System.out.println(i.next().getName() + " was born in 1980");
}
//city mode, print out persons who live in New York City
i.cityMode("New York");
while (i.hasNext()){
System.out.println(i.next().getName() + " lives in NYC");
}
Here is the result.
john is in the list
adam is in the list
lucy is in the list
john was born in 1980
adam was born in 1980
john lives in NYC
lucy lives in NYC
So my question is:
-
Is my approach a solution to the problem? If not, please point out a better approac.
-
Is the code easy to read, easy to modify? If not, how to improve?
Aucun commentaire:
Enregistrer un commentaire