
7.5 原型模式重构代码
原型模式主要解决的问题是创建大量的重复对象,而这里模拟的场景同样是需要给不同的考生创建相同的试卷,但在创建过程中,这些试卷的题目不应该每次都从数据库或者远程 RPC 接口中获取。这些操作都是非常耗时的,而且随着创建对象的增多,将严重降低创建效率。
另外,在解决获取相同试卷题目的问题后,还需要将试卷的题目与答案混排。而这种混排的过程就可以使用原型模式。在原型模式中,需要的重要技术手段是复制,而在需要用到复制的类中需要实现implements Cloneable接口。
7.5.1 工程结构

原型模式代码类关系如图7-3所示。

图7-3
重构后的整个工程结构并不复杂,主要包括如下内容:
·题目类ChoiceQuestion、AnswerQuestion被用在题库创建中;
·针对每一张试卷,都会复制。复制完成后,将试卷的题目及相应的答案混排。这里提供了工具包TopicRandomUtil。
·核心的题库类QuestionBank主要负责将各个题目进行组装,最终输出试卷。
7.5.2 题目混排工具包


考题答案混排的工具包提供了实现混排的random方法。其核心逻辑如下:
·在混排操作方法中,首先把题目选项使用 Java 中 Collections 工具包里的shuffle方法进行混排操作;
·记录混排后正确答案的位置key.equals(next),最终返回新的题目选项单Topic;
·混排的过程也就是把A的选项内容给B、把B的选项内容给 C,同时把正确答案位置标记出来。
7.5.3 题库复制对象类



这个类中的操作内容主要包括以下三个方面:
·两个 append()对各项题目的添加有点像在建造者模式中使用的方式——添加装修材料。
·clone()的核心操作是复制对象,这里的复制不仅包括对象本身,也包括两个集合。只有这样的复制才能确保在操作复制对象时不影响原对象。
·混排操作在list集合中有一个方法——Collections.shuffle,可以将原有集合的顺序打乱,输出一个新的顺序。这里使用此方法对题目进行混排操作。
7.5.4 初始化试卷数据


这个类的内容就比较简单了,主要提供对试卷内容的模式初始化操作(所有考生的试卷一样,但题目顺序不一致)。
对外部提供创建试卷的方法,在创建的过程中使用的是复制的方式(QuestionBank) questionBank.clone();,并最终返回试卷信息。
7.5.5 测试验证
1.单元测试

2.测试结果




从以上的输出结果可以看到,每位考生的题目和答案都是有差异的,如图7-4所示。

图7-4