我有一个有趣的设计问题,我将尝试简化下面的玩具问题:
我希望设计一个系统,根据某些输入和中间处理,输出将是学生对象。流程如下:我有一个教室列表作为一种输入。要生成输出,处理步骤为:
另一个输入可以只是我已经拥有的学生列表,并希望作为结果的一部分包含在内。例如:输入1:3名学生的列表,输入2:将运行上述处理步骤的2个教室的列表。
设计这样一个输入的系统的最佳方法是:
{student list|classroom list}
,{age|height|etc}
,{any ordering of height,weight,arm length}
,{how many students to return}
系统应足够灵活,以容纳更多输入类型和更多排序顺序条目{即。按鞋码分类学生}。我可以使用什么数据结构来模拟本节的每个部分(即,表示排序顺序标准的最佳方式是什么?)是否有适合这些需求的设计模式?任何有关建筑设计的帮助都将不胜感激!
答案 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)
根据要求,尽管Student
和Classroom
都是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”一书中阅读。
你没有多说:
Comparator
传递给哪个Java集合有关; 所以手头的任务归结为:
if passesAllFilters(student) okstudents.add(student);
okstudents
java.util.TreeSet
Comparator
为List<Filter<Student>> getFilters(String filterSpec)
,{达到。您可能会狡辩地说,采用“定义过滤器的输入”的步骤是“工厂方法”,但这实际上没有任何帮助。<!-- 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。