文章目录
原型模式(Prototype Pattern)
原型模式的定义
- 原型模式(Prototype Pattern)
- 原型模式的定义
- 原型模式的优点
- 原型模式的缺点
- 原型模式的结构
- 原型模式的实现
- 使用场景
- 注意事项
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式的优点- Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
- 需要为每一个类都配置一个 clone 方法
- clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
原型模式包含以下主要角色。
- 抽象原型类:规定了具体原型对象必须实现的接口。
- 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
package org.donny.design.patterns.prototypePattern;
/**
* 解答题
*/
public class AnswerQuestion {
/**
* 问题
*/
private String name;
/**
* 答案
*/
private String key;
public AnswerQuestion() {
}
public AnswerQuestion(String name, String key) {
this.name = name;
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
package org.donny.design.patterns.prototypePattern;
import java.util.Map;
/**
* 单选题
*/
public class ChoiceQuestion {
/**
* 题目
*/
private String name;
/**
* 选项;A、B、C、D
*/
private Map option;
/**
* 答案;B
*/
private String key;
public ChoiceQuestion() {
}
public ChoiceQuestion(String name, Map option, String key) {
this.name = name;
this.option = option;
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map getOption() {
return option;
}
public void setOption(Map option) {
this.option = option;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
package org.donny.design.patterns.prototypePattern;
import java.util.Map;
public class Topic {
/**
* 选项;A、B、C、D
*/
private Map option;
/**
* 答案
*/
private String key;
public Topic() {
}
public Topic(Map option, String key) {
this.option = option;
this.key = key;
}
public Map getOption() {
return option;
}
public void setOption(Map option) {
this.option = option;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
package org.donny.design.patterns.prototypePattern;
import java.util.*;
public class TopicRandomUtil {
/**
* 乱序Map元素,记录对应答案key
*
* @param option 题目
* @param key 答案
* @return Topic 乱序后 {A=c., B=d., C=a., D=b.}
*/
static public Topic random(Map option, String key) {
Set keySet = option.keySet();
ArrayList keyList = new ArrayList(keySet);
Collections.shuffle(keyList);
HashMap 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 Topic(optionNew, keyNew);
}
}
具体原型类问卷实现clone方法
package org.donny.design.patterns.prototypePattern;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
public class QuestionBank implements Cloneable {
/**
* 考生
*/
private String candidate;
/**
* 考号
*/
private String number;
private ArrayList choiceQuestionList = new ArrayList();
private ArrayList answerQuestionList = new ArrayList();
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) choiceQuestionList.clone();
questionBank.answerQuestionList = (ArrayList) answerQuestionList.clone();
// 题目乱序
Collections.shuffle(questionBank.choiceQuestionList);
Collections.shuffle(questionBank.answerQuestionList);
// 答案乱序
ArrayList 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;
}
public void setCandidate(String candidate) {
this.candidate = candidate;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public String toString() {
StringBuilder detail = new StringBuilder("考生:" + candidate + "\r\n" +
"考号:" + number + "\r\n" +
"--------------------------------------------\r\n" +
"一、选择题" + "\r\n\n");
for (int idx = 0; idx
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?