创建型-原型模式 Link to heading
原型模式主要解决的问题就是创建重复对象,而这部分对象内容本身比较复杂,生成过程可能从库或者RPC接口中获取数据的耗时较长,因此采用克隆的方式节省时间。
这种场景就像CV代码、java中的clone一样。
模拟场景 Link to heading
一个上机考试抽题服务,做到能够混排题目,混排答案。这个服务用于选择题、问答题的试卷创建。
数据准备
public class ChoiceQuestion{
private String name;
private Map<String, String> option;
private String key;
public ChoiceQuestion(String name. Map<String, String> option, String key){
this.name = name;
this. option = option;
this. key = key;
}
}
public class AnswerQuestion{
private String name;
private String key;
public AnswerQuestion(String name,String key){
this.name = name;
this.key = key;
}
}
最初设计 Link to heading
public class QuestionBankController{
public String createPaper(Stirng candidate, String number){
// do sth
// 手工填写不同问题
}
}
这样的代码非常容易理解,要什么题目就塞进去,只面向过程,不考虑扩展性。
以上的代码有一个没有实现的地方就是不能乱序,所有人的试卷都是一样的。
改进方案 Link to heading
工程结构
└─design
├─util
│ ├─Topic.java
│ └─TopicRandomUtil.java
├─QuestionBank.java
└─QuestionBankController.java
- 工程中包含了核心的题库类QuestionBank,题库主要负责将各个的题目进行组装最终输出试卷。
- 针对每一个试卷都会使用克隆的方式进行复制,复制完成后将试卷中的题目以及每个题目的答案进行乱序处理。
乱序工具包
public class TopicRandomUtil{
static public Topic random(Map<String, String> optionn, String key){
Set<String> keySet = option.keySet();
ArrayList<String> keyList = new ArrayList<String>(keySet);
Collections.shuffle(keyList);
HashMap<String, String> optionNew = new HashMap<String, String>();
int idx = 0;
String keyNew = "";
for (String next : keySet) {
String randomKey = keyList.get(idx++);
if (key.equals(next)) {
keyNew = randomKey;
}
optionNew.put(randomKey, option.get(next));
}
return new Topic(optionNew, keyNew);
}
}
克隆对象处理类
public class QuestionBank implements Cloneable{
private String candidate;
private String number;
private ArrayList<ChoiceQuestion> choiceQuestionList = new ArrayList<ChoiceQuestion>();
private ArrayList<AnswerQuestion> answerQuestionList = new
ArrayList<AnswerQuestion>();
// 添加题目
public QuestionBank append(ChoiceQuestion choiceQuestion) {
choiceQuestionList.add(choiceQuestion);
return this;
}
public QuestionBank append(AnswerQuestion answerQuestion) {
answerQuestionList.add(answerQuestion);
return this;
}
@Override
public Object clone() throws CLoneNotSupportedException{
QuestionBank questionBank = (QuestionBank) super.clone();
questionBank.choiceQuestionList = (ArrayList<ChoiceQuestion>) choiceQuestionList.clone();
questionBank.answerQuestionList = (ArrayList<AnswerQuestion>) answerQuestionList.clone();
// 题目乱序
Collections.shuffle(questionBank.choiceQuestionList);
Collections.shuffle(questionBank.answerQuestionList);
// 答案乱序
ArrayList<ChoiceQuestion> choiceQuestionList = questionBank.choiceQuestionList;
for (ChoiceQuestion question : choiceQuestionList) {
Topic random = TopicRandomUtil.random(question.getOption(),question.getKey());
question.setOption(random.getOption());
question.setKey(random.getKey());
}
return questionBank;
}
}
这里的操作主要三个
- 两个
append()对题目的添加 clone(),这里的核心操作就是对对象的复制,这里复制不只包含了本身,同时对两个集合也做了复制。- 乱序操作,使用的是
lsit的Collections.shuffle可以将原有的集合打乱。
初始化试卷数据
public class QuestionBankController{
private QUestionBank questionBank = new QuestionBank();
public QuestionBankController(){
// do sth
}
public String createPaper(String candidate, String number) throws CloneNotSupportedException{
QuestionBank questionBankClone = (QuestionBank) questionBank.clone();
// do sth
return questionBankClone.toString();
}
}