可配置系统的设计模式

时间:2015-10-25 18:11:24

标签: java sorting design-patterns

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

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

  1. 由X岁以下的学生(简称10)过滤每个教室
  2. 按此层次顺序的任何排列对过滤后的结果进行排序:身高,体重,手臂长度
  3. 返回前8名学生。
  4. 另一个输入可以只是我已经拥有的学生列表,并希望作为结果的一部分包含在内。例如:输入1:3名学生的列表,输入2:将运行上述处理步骤的2个教室的列表。

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

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

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

4 个答案:

答案 0 :(得分:7)

嗯,您建议的内容可以通过Java 8流轻松完成,因此我猜您可以遵循的一种模式是pipeline。您也可以使用internal iterators实现此目的:

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());

答案 1 :(得分:2)

根据要求,尽管StudentClassroom都是StudentSource,但过滤和排序始终会对Student起作用(它们永远不会被教室过滤或排序,在您的样本输入中)。过滤非常简单:

// 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);
}

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

你没有多说:

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

所以手头的任务归结为:

  1. 阅读过滤器,分拣机,限制器的定义,为这些
  2. 创建访客
  3. 阅读数据(教室/学生),对于发现的每个学生,if passesAllFilters(student) okstudents.add(student); okstudents java.util.TreeSet ComparatorList<Filter<Student>> getFilters(String filterSpec),{达到。
  4. 您可能会狡辩地说,采用“定义过滤器的输入”的步骤是“工厂方法”,但这实际上没有任何帮助。<!-- Form --> <h1>Pease Login to Upload CV</h1> <form method="POST" enctype="multipart/form-data"> Username: <input type="text" name="username"><br> Password: <input type="password" name="password"><br><br> <input type="submit" value="Submit" name="submit" /> <br> </form> 并不能真正让你到达任何地方工厂方法有用。解析过滤器并提出引用学生特定属性的代码,应用表达式等,可能不是一项简单的任务。根据您的过滤器需要允许的表达式类型,您可能需要查看像ANTLR 4这样的编译器生成器。您可能需要使用反射。

答案 2 :(得分:2)

看看https://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html

你可以使用多个SortedMap(每个键一个),在其中你将列表的每个元素都放在每个地图的相应键中(es:sortedMapAge.put(carl,18)..sortedMapHeight(carl,&# 34; 1.75&#34;)......)。

因此,使用迭代器,您可以使用相应的SortedMap通过varius键访问列表成员。

如果你想在另一个抽象层中存储alla,你可以将它们存储在一个hashmap中,并使用密钥标识符作为键(sortedMapAge ... key Age,sortedMapHeight height ....)

它非常棘手但是地图为您提供了使用键集组织对象的好方法。

答案 3 :(得分:0)

就个人而言,我会这样做:

public <E> List<E> query(List<E> dataset, Filter<E> filter, Comparator<E> sortOrder, int maxResults);

也就是说,我使用泛型来抽象输入类型,过滤器和命令的命令模式,以及要返回的结果数的普通int。