Reputation: 1762
Let's say, I have a complex object hierarchy, something like:
public class ClassRoom
{
private ClassRoomInfo classRoomInfo;
private List<Student> students;
...
}
I get this object as an input from client, but the object might not be filled completely. For example, client can provide very minimal details like studentId(s)
or minor information in the classRoomInfo
object. I want to write a DataCollector
class for this object, which would collect all the missing data upfront.
What would be the best design pattern in this case?
Upvotes: 2
Views: 5994
Reputation: 47243
Here's one approach. The idea is to treat the ClassRoom
as an instance of the composite pattern, where every object in the hierarchy knows how to "fill itself in" using a DataCollector
. If an object is already filled in, it responds to being asked to fill itself in by returning itself; if it is not filled in, it gets the necessary information from the DataCollector
and builds a new instance of its own class which is filled in (the objects themselves are therefore immutable - you might prefer to have the objects mutate themselves, but i usually lean towards using immutable objects to represent data).
I've defined an interface Fillable
for objects which know how to fill themselves in. However, this isn't really necessary, as the fillIn
method is never invoked polymorphically. It's just documentation, really.
I've assumed that the filling-in process is pretty simple. Obviously, it could be more complex, both in detecting what is filled in (eg an empty list of students might indicate that the list has not been populated), and in how it goes about filling it in. If you applied this design to your real problem, you will find that the DataCollector
becomes incredibly complicated. You will need to factor it differently; you might want to move more of the collection logic into the domain classes, or to split it into per-class DAOs (ClassRoomInfoDataCollector
etc).
public interface Fillable<T> {
public T fillIn(DataCollector collector);
}
public class ClassRoom implements Fillable<ClassRoom> {
private final ClassRoomInfo classRoomInfo;
private final List<Student> students;
private ClassRoom(ClassRoomInfo classRoomInfo, List<Student> students) {
this.classRoomInfo = classRoomInfo;
this.students = students;
}
@Override
public ClassRoom fillIn(DataCollector collector) {
ClassRoomInfo filledInClassRoomInfo = classRoomInfo.fillIn(collector);
List<Student> filledInStudents = new ArrayList<Student>();
for (Student student : students) {
filledInStudents.add(student.fillIn(collector));
}
if (filledInClassRoomInfo == classRoomInfo && filledInStudents.equals(students)) return this;
return new ClassRoom(filledInClassRoomInfo, filledInStudents);
}
}
public class ClassRoomInfo implements Fillable<ClassRoomInfo> {
final String roomNumber;
final Integer capacity;
private ClassRoomInfo(String roomNumber, int capacity) {
this.roomNumber = roomNumber;
this.capacity = capacity;
}
@Override
public ClassRoomInfo fillIn(DataCollector collector) {
if (capacity != null) return this;
return new ClassRoomInfo(roomNumber, collector.getClassRoomCapacity(roomNumber));
}
}
public class Student implements Fillable<Student> {
final int id;
final String name;
private Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public Student fillIn(DataCollector collector) {
if (name != null) return this;
return new Student(id, collector.getNameOfStudent(id));
}
}
public class DataCollector {
public String getNameOfStudent(int id) {
...
}
public int getClassRoomCapacity(String roomNumber) {
...
}
}
Upvotes: 2
Reputation: 479
I think you need to Lazy Load data when needed.The getters for the members of ClassRoom
class should suffice for this purpose.
A separate DataCollector
class is not recommended as it will force you to expose setters in ClassRoom
for all members.
This link (and Book) should tell you more about Lazy load .
Upvotes: 2
Reputation: 866
Try "Facade Design Pattern". Hope it can help you. you can find a good description on Facade in http://javapapers.com/design-patterns/facade-design-pattern/
Upvotes: 0