Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here's one approach. The idea is to treat the <code>ClassRoom</code> as an instance of the <a href="http://en.wikipedia.org/wiki/Composite_pattern" rel="nofollow">composite pattern</a>, where every object in the hierarchy knows how to "fill itself in" using a <code>DataCollector</code>. 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 <code>DataCollector</code> 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).</p> <p>I've defined an interface <code>Fillable</code> for objects which know how to fill themselves in. However, this isn't really necessary, as the <code>fillIn</code> method is never invoked polymorphically. It's just documentation, really.</p> <p>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 <code>DataCollector</code> 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 (<code>ClassRoomInfoDataCollector</code> etc).</p> <pre><code>public interface Fillable&lt;T&gt; { public T fillIn(DataCollector collector); } public class ClassRoom implements Fillable&lt;ClassRoom&gt; { private final ClassRoomInfo classRoomInfo; private final List&lt;Student&gt; students; private ClassRoom(ClassRoomInfo classRoomInfo, List&lt;Student&gt; students) { this.classRoomInfo = classRoomInfo; this.students = students; } @Override public ClassRoom fillIn(DataCollector collector) { ClassRoomInfo filledInClassRoomInfo = classRoomInfo.fillIn(collector); List&lt;Student&gt; filledInStudents = new ArrayList&lt;Student&gt;(); for (Student student : students) { filledInStudents.add(student.fillIn(collector)); } if (filledInClassRoomInfo == classRoomInfo &amp;&amp; filledInStudents.equals(students)) return this; return new ClassRoom(filledInClassRoomInfo, filledInStudents); } } public class ClassRoomInfo implements Fillable&lt;ClassRoomInfo&gt; { 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&lt;Student&gt; { 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) { ... } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload