简体   繁体   English

良好的设计模式,用于收集复杂对象中的数据

[英]Good design pattern to collect data in a complex object

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. 例如,客户端可以在classRoomInfo对象中提供非常小的详细信息,如studentId(s)或次要信息。 I want to write a DataCollector class for this object, which would collect all the missing data upfront. 我想为这个对象编写一个DataCollector类,它会预先收集所有丢失的数据。

What would be the best design pattern in this case? 在这种情况下,最好的设计模式是什么?

I think you need to Lazy Load data when needed.The getters for the members of ClassRoom class should suffice for this purpose. 我认为在需要时你需要延迟加载数据ClassRoom类成员的getter应该足以满足这个目的。

A separate DataCollector class is not recommended as it will force you to expose setters in ClassRoom for all members. 建议不要使用单独的DataCollector类,因为它会强制您在ClassRoom为所有成员公开setter。

This link (and Book) should tell you more about Lazy load . 链接 (和Book)应该告诉您有关延迟加载的更多信息。

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 . 我们的想法是将ClassRoom视为复合模式的一个实例,其中层次结构中的每个对象都知道如何使用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). 如果它没有被填充,它从DataCollector获取必要的信息并构建一个自己的类的新实例,它被填充(对象本身因此是不可变的 - 你可能更愿意让对象自己变异,但我通常倾斜使用不可变对象来表示数据)。

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. 我定义的接口Fillable用于其知道如何填写自己的对象。然而,这是不是真的有必要,因为fillIn方法永远不会调用多态。 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. 显然,它可能更复杂,无论是在检测填充的内容(例如,空的学生列表可能表明列表尚未填充),以及如何填写它。如果您将此设计应用于您的真正的问题,你会发现DataCollector变得异常复杂。 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). 您可能希望将更多的集合逻辑移动到域类中,或者将其拆分为每类DAO( ClassRoomInfoDataCollector等)。

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) {
        ...
    }
}

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/ 你可以在http://javapapers.com/design-patterns/facade-design-pattern/找到关于Facade的好描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM