可配置系统的设计模式

2022-09-03 15:21:27

我有一个有趣的设计问题,我将尝试在下面的玩具问题中简化:

我希望设计一个系统,其输出将是基于某些输入和中间处理的学生对象。流程如下:我有一个教室列表作为一种类型的输入。要生成输出,处理步骤如下:

  1. 按 X 岁以下(假设 10 岁)的学生筛选每个教室
  2. 按以下层次结构顺序的任何排列对筛选结果进行排序:身高、体重、臂长
  3. 返回前 8 名学生。

另一个输入可以只是我已经拥有并希望作为结果的一部分包含的学生列表。例如:输入 1:3 名学生的列表,输入 2:将运行上述处理步骤的 2 间教室的列表。

设计这样一个输入系统的最佳方法是:

  • 输入类型 ,{student list|classroom list}
  • 过滤器类型 ,{age|height|etc}
  • 排序顺序,{any ordering of height,weight,arm length}
  • 返回次数{how many students to return}

该系统应该足够灵活,以适应更多的输入类型和更多的排序顺序条目{即按鞋码对学生进行排序}。我可以使用什么数据结构来对本节的每个部分进行建模(即表示排序顺序标准的最佳方法是什么?是否有任何设计模式可以满足这些需求?任何有关架构设计的帮助将不胜感激!


答案 1

好吧,你所建议的可以用Java 8流轻松完成,所以我想你可以遵循的一个模式是管道。您还可以使用内部迭代器实现此目的:

List<Student> found = Stream.of(student1, student2, student3, ..., studentn)
    .filter(s -> s.getAge() > 100)
    .sorted(Comparator.comparing(Student::getHeight).thenComparing(Student::getWeight))
    .limit(10)
    .collect(Collectors.toList());

答案 2

从要求来看,尽管两者和都是s,但过滤和排序始终起作用(在示例输入中,它们永远不会按教室过滤或排序)。过滤非常简单:StudentClassroomStudentSourceStudent

// interface with a single method, reduces to a lambda too
interface Filter<T> {
    boolean accept(T candidate);
}

排序是规范的:

package java.util;
// interface with a single method, reduces to a lambda too
interface Comparable<T> {
    int compareTo(T a, T b);
}

以上两者都是设计模式的应用。与@Edwin简洁的答案一样,您将访问者排在管道(配置阶段)中,然后访问它们(执行阶段)。请注意,访客模式有“原因”,嗯,学生应该在他们的“4人帮”书中阅读。Visitor

你没有说太多:

  • 如何将输入表示到程序中(例如,作为需要解析的文本)
  • 同一个学生是否可能出现在1个以上的教室中,或者学生名单......这与您可能选择传递给哪个Java集合有关;Comparator

因此,手头的任务归结为:

  1. 阅读过滤器,分类器,限制器的定义,为这些创建访问者
  2. 读取数据(教室/学生),并为每个发现的学生,在达到极限时停止。if passesAllFilters(student) okstudents.add(student);okstudentsjava.util.TreeSetComparator

你可能会质疑“定义过滤器的输入”的步骤是一个“工厂方法”,但这真的无济于事。 并没有真正让你去任何工厂方法有用的地方。解析过滤器并提出引用学生特定属性,应用表达式等的代码可能不是一件容易的事。根据筛选器需要允许的表达式类型,您可能需要查看 ANTLR 4 等编译器生成器。您可能需要使用反射。List<Filter<Student>> getFilters(String filterSpec)


推荐