目录
一、案例
1.1 不用模式来实现
选择题类:
@Data
public class ChoiceQuestion {
/**
* 选择题题目
*/
private String title;
/**
* 选项
*/
private Map<String, String> options;
/**
* 答案
*/
private String key;
public ChoiceQuestion(){}
public ChoiceQuestion(String title, Map<String, String> options, String key) {
this.title = title;
this.options = options;
this.key = key;
}
}
填空题类:
@Data
public class Completion {
/**
* 填空题题目
*/
private String title;
/**
* 答案
*/
private List<String> key;
public Completion() {}
public Completion(String title, List<String> key) {
this.title = title;
this.key = key;
}
}
试卷类:
public class TestPaper {
/**
* 创建试卷
* @param name 考生姓名
* @param code 考生编号
* @return
*/
public String createPaper(String name, String code) {
// 这里举例有两道选择题和两道填空题
List<ChoiceQuestion> choiceQuestionList = new ArrayList<>(2);
List<Completion> completionList = new ArrayList<>(2);
// 初始化选择题
Map<String, String> choiceMap1 = new HashMap<>();
choiceMap1.put("A", "1");
choiceMap1.put("B", "2");
choiceMap1.put("C", "3");
choiceMap1.put("D", "4");
Map<String, String> choiceMap2 = new HashMap<>();
choiceMap2.put("A", "1");
choiceMap2.put("B", "2");
choiceMap2.put("C", "3");
choiceMap2.put("D", "4");
choiceQuestionList.add(new ChoiceQuestion("1 + 1 = ", choiceMap1, "B"));
choiceQuestionList.add(new ChoiceQuestion("3 + 1 = ", choiceMap2, "D"));
// 初始化填空题
List<String> comList1 = new ArrayList<>();
comList1.add("富强");
comList1.add("民主");
List<String> comList2 = new ArrayList<>();
comList2.add("51");
comList2.add("21");
completionList.add(new Completion("任意列举出两个社会主义核心价值观", comList1));
completionList.add(new Completion("2008年中国获得金牌数___枚,银牌___枚", comList2));
String newLine = "\n";
// 组装试卷
StringBuffer strBuff = new StringBuffer();
strBuff.append("考生:").append(name).append(newLine)
.append("考号:").append(code).append(newLine)
.append("一、选择题").append(newLine);
for (ChoiceQuestion choiceQuestion : choiceQuestionList) {
strBuff.append(choiceQuestion.getTitle()).append(newLine);
for (Map.Entry<String, String> entry : choiceQuestion.getOptions().entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
strBuff.append(key).append(":").append(value).append(newLine);
}
strBuff.append("答案:").append(choiceQuestion.getKey()).append(newLine);
}
for (Completion completion : completionList) {
strBuff.append(completion.getTitle()).append(newLine);
strBuff.append("答案:");
for (String anster : completion.getKey()) {
strBuff.append(" ").append(anster);
}
}
return strBuff.toString();
}
}
测试客户端:
public class Client {
public static void main(String[] args) {
TestPaper testPaper = new TestPaper();
System.out.println(testPaper.createPaper("张三", "ACCDF0001"));
System.out.println(testPaper.createPaper("李四", "ACCDF0002"));
System.out.println(testPaper.createPaper("王五", "ACCDF0003"));
}
}
运行结果如下:
考生:张三
考号:ACCDF0001
一、选择题
1 + 1 =
A:1
B:2
C:3
D:4
答案:B
3 + 1 =
A:1
B:2
C:3
D:4
答案:D
任意列举出两个社会主义核心价值观
答案: 富强 民主
2008年中国获得金牌数___枚,银牌___枚
答案: 51 21
考生:李四
考号:ACCDF0002
一、选择题
1 + 1 =
A:1
B:2
C:3
D:4
答案:B
3 + 1 =
A:1
B:2
C:3
D:4
答案:D
任意列举出两个社会主义核心价值观
答案: 富强 民主
2008年中国获得金牌数___枚,银牌___枚
答案: 51 21
考生:王五
考号:ACCDF0003
一、选择题
1 + 1 =
A:1
B:2
C:3
D:4
答案:B
3 + 1 =
A:1
B:2
C:3
D:4
答案:D
任意列举出两个社会主义核心价值观
答案: 富强 民主
2008年中国获得金牌数___枚,银牌___枚
答案: 51 21
一坨坨代码很快就实现了,看上去很简单。
1.2 有何问题
1.3 原型模式重构代码
用原型模式注意要点:
代码改造
添加选项答案类:
@Data
public class Option {
/**
* 选项
*/
private Map<String, String> options;
/**
* 答案
*/
private String key;
public Option(Map<String, String> options, String key) {
this.options = options;
this.key = key;
}
}
添加选项乱序工具类:
public class RandomUtil {
/**
* 乱序Map元素,记录对应答案key
* @param option 题⽬选项
* @param key 答案
* @return Option 乱序后 {A=c., B=d., C=a., D=b.} */
static public Option random(Map<String, String> option, String key) {
Set<String> keySet = option.keySet();
ArrayList<String> keyList = new ArrayList<>(keySet);
Collections.shuffle(keyList);
HashMap<String, String> optionNew = new HashMap<>();
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 Option(optionNew, keyNew);
}
}
添加题库类:
@Data
public class QuestionBank implements Cloneable {
/**
* 试卷序号
*/
private String seq;
/**
* 考生姓名
*/
private String name;
/**
* 考生考号
*/
private String code;
private ArrayList<ChoiceQuestion> choiceQuestionList = new ArrayList<>(2);
private ArrayList<Completion> completionList = new ArrayList<>(2);
/**
* 实现中题目可能来自数据库中,这里示例便直接写死
*/
public QuestionBank() {
// 初始化选择题
Map<String, String> choiceMap1 = new HashMap<>();
choiceMap1.put("A", "1");
choiceMap1.put("B", "2");
choiceMap1.put("C", "3");
choiceMap1.put("D", "4");
Map<String, String> choiceMap2 = new HashMap<>();
choiceMap2.put("A", "1");
choiceMap2.put("B", "2");
choiceMap2.put("C", "3");
choiceMap2.put("D", "4");
this.choiceQuestionList.add(new ChoiceQuestion("1 + 1 = ", choiceMap1, "B"));
this.choiceQuestionList.add(new ChoiceQuestion("3 + 1 = ", choiceMap2, "D"));
// 初始化填空题
List<String> comList1 = new ArrayList<>();
comList1.add("富强");
comList1.add("民主");
List<String> comList2 = new ArrayList<>();
comList2.add("51");
comList2.add("21");
this.completionList.add(new Completion("任意列举出两个社会主义核心价值观", comList1));
this.completionList.add(new Completion("2008年中国获得金牌数___枚,银牌___枚", comList2));
}
@Override
public QuestionBank clone() {
try {
QuestionBank questionBank = (QuestionBank) super.clone();
questionBank.setChoiceQuestionList((ArrayList<ChoiceQuestion>) this.getChoiceQuestionList().clone());
questionBank.setCompletionList((ArrayList<Completion>) this.getCompletionList().clone());
// 打乱选择题
Collections.shuffle(questionBank.getChoiceQuestionList());
// 选择题的选项打乱
for (ChoiceQuestion choiceQuestion : questionBank.getChoiceQuestionList()) {
Option option = RandomUtil.random(choiceQuestion.getOptions(), choiceQuestion.getKey());
choiceQuestion.setOptions(option.getOptions());
choiceQuestion.setKey(option.getKey());
}
// 打乱填空题
Collections.shuffle(questionBank.getCompletionList());
return questionBank;
} catch (Exception e) {
throw new AssertionError();
}
}
@Override
public String toString() {
String newLine = "\r\n";
StringBuffer strBuff = new StringBuffer();
strBuff.append("考卷:").append(getSeq()).append(newLine)
.append("考生:").append(getName()).append(newLine)
.append("考号:").append(getCode()).append(newLine);
strBuff.append("一、选择题").append(newLine);
for (ChoiceQuestion choiceQuestion : getChoiceQuestionList()) {
strBuff.append(choiceQuestion.getTitle()).append(newLine);
for (Map.Entry<String, String> entry : choiceQuestion.getOptions().entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
strBuff.append(key).append(":").append(value).append(newLine);
}
strBuff.append("答案:").append(choiceQuestion.getKey()).append(newLine);
}
strBuff.append("一、填空题").append(newLine);
for (Completion completion : getCompletionList()) {
strBuff.append(completion.getTitle()).append(newLine);
strBuff.append("答案:");
for (String anster : completion.getKey()) {
strBuff.append(" ").append(anster);
}
}
return strBuff.toString();
}
}
试卷类改造:
@Data
public class TestPaper {
/**
* 题库
*/
QuestionBank questionBank = new QuestionBank();
/**
* 创建试卷
* @param req 试卷序号
* @param name 考生姓名
* @param code 考生编号
* @return
*/
public String createPaper(String req, String name, String code) {
QuestionBank questionBankClone = this.getQuestionBank().clone();
questionBankClone.setSeq(req);
questionBankClone.setName(name);
questionBankClone.setCode(code);
return questionBankClone.toString();
}
}
改造测试客户端:
public class Client {
public static void main(String[] args) {
// 创建试卷工具类并初始化题库
TestPaper testPaper = new TestPaper();
// 创建张三
System.out.println(testPaper.createPaper("A", "张三", "A0001"));
System.out.println(testPaper.createPaper("B", "李四", "A0002"));
System.out.println(testPaper.createPaper("C", "王五", "A0003"));
}
}
运行结果如下:
(考卷A)
考卷:A
考生:张三
考号:A0001
一、选择题
1 + 1 =
A:3
B:1
C:2
D:4
答案:C
3 + 1 =
A:3
B:1
C:4
D:2
答案:C
一、填空题
2008年中国获得金牌数___枚,银牌___枚
答案: 51 21
任意列举出两个社会主义核心价值观
答案: 富强 民主
(考卷B)
考卷:B
考生:李四
考号:A0002
一、选择题
3 + 1 =
A:4
B:1
C:2
D:3
答案:A
1 + 1 =
A:2
B:4
C:3
D:1
答案:A
一、填空题
2008年中国获得金牌数___枚,银牌___枚
答案: 51 21
任意列举出两个社会主义核心价值观
答案: 富强 民主
(考卷C)
考卷:C
考生:王五
考号:A0003
一、选择题
1 + 1 =
A:1
B:4
C:3
D:2
答案:D
3 + 1 =
A:4
B:3
C:1
D:2
答案:A
一、填空题
任意列举出两个社会主义核心价值观
答案: 富强 民主
2008年中国获得金牌数___枚,银牌___枚
答案: 51 21
1.4 完美实现
从上面结果看出,A卷、B卷和C卷的题目和选项都被打乱了。再添加DEF等卷,就完美实现了案例场景下我座位中前后左右人的卷子与我不同的情况。
三、模式讲解
3.1 功能
原型模式 的功能 实际上包含两个方面:
3.2 原型模式的结构和说明
- Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求它们都要实现这里定义的克隆方法。
- ConcretePrototype:实现Prototype接口的类,这些类真正实现了克隆自身的功能。
- Client:使用原型的客户端,首先获取到原型对象,然后通过原型实例克隆自身来创建新的对象实例。
3.3 几种工厂模式总结
工厂方法、抽象工厂、建造者模式和原型模式是常见的软件设计模式,它们各自解决了不同类型的设计问题。
区别: