原型模式简介及作用

目录

一、概念:

二、代码示例


一、概念:

原型模式主要解决的是创建重复对象的问题,用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和实例原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。该模式最显著的一个特征就是对象的克隆

模式的结构特点:

1.抽象原型类:具体原型对象继承后必须要实现的接口;

2.具体原型类:实现抽象原型类的clone()方法,它是可以被复制的对象,即原型模式中的那个原型对象;

3.访问类:使用具体原型类中的clone()方法来复制新的对象;

优点:

  • 性能提高,java自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
  • 逃避构造函数的约束,可以直接克隆已有的实例对象。

缺点:

  • 要为每一个类都配置一个 clone 方法
  • clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。

二、代码示例

下面我们就建一个模拟工程,示例的大体业务场景是为学生创建一套试卷,试卷由选择题组成,创建试卷的时候,每个学生的选择题顺序不一致,同时每个选择的选项顺序也不一致;下面我们就一起通过代码来看看实现的过程是什么样的;

1.选择题类

import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.util.Map;

/**
 * @Description: 选择题类
 * @Author: yangshilei
 */
@Data
public class ChoiceQuestion {

    /**
     * 题目名称
     */
    private String name;

    /**
     * 题目选项:A/B/C/D等
     */
    private Map<String,String> option;

    /**
     * 答案
     */
    private String key;

    public ChoiceQuestion(){}

    public ChoiceQuestion(String name, Map<String, String> option, String key) {
        this.name = name;
        this.option = option;
        this.key = key;
    }

    @Override
    public String toString () {
        return JSONObject.toJSONString(this);
    }
}

2.考生试卷类:(抽象原型类)

import lombok.Data;

import java.util.ArrayList;
import java.util.Collections;

/**
 * @Description: 试卷的选择题复制对象类
 * @Author: yangshilei
 */
@Data
public class QuestionBank implements Cloneable {

    /**
     * 考生
     */
    private String candidate;

    /**
     * 学号
     */
    private String number;

    /**
     * 选择题集合
     */
    private ArrayList<ChoiceQuestion> choiceQuestionList = new ArrayList<ChoiceQuestion>();

    /**
     * 此处类似建造者方法
     */
    public QuestionBank append(ChoiceQuestion choiceQuestion) {
        choiceQuestionList.add(choiceQuestion);
        return this;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        QuestionBank questionBank = (QuestionBank) super.clone();
        questionBank.choiceQuestionList = (ArrayList<ChoiceQuestion>) choiceQuestionList.clone();

        // 题目混排
        Collections.shuffle(questionBank.choiceQuestionList);

        // 题目的选项及答案混排
        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;
    }

}

3.选择题组成类,用于给选择题混排;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.util.Map;

/**
 * 题目选项单及答案组成类
 */
@Data
public class Topic {

    /**
     * 题目选项:A/B/C/D等
     */
    private Map<String,String> option;

    /**
     * 答案
     */
    private String key;


    public Topic(Map<String,String> option,String key){
        this.option = option;
        this.key = key;
    }

    @Override
    public String toString () {
        return JSONObject.toJSONString(this);
    }
}

4.选择题混排工具类

import java.util.*;

/**
 * 选择题选项即题目混排的工具类
 */
public class TopicRandomUtil {

    /**
     * 混排Map元素,记录对应的答案key
     * @param option 选项
     * @param key 答案
     * @return
     */
    public static Topic random(Map<String,String> option,String key) {
        Set<String> keySet = option.keySet();
        List<String> keyList = new ArrayList<>(keySet);
        Collections.shuffle(keyList);

        Map<String,String> optionNew = new HashMap<>();

        int idx = 0;
        String newKey = "";
        for(String next : keySet){
            String randomKey = keyList.get(idx++);
            if(key.equals(next)){
                newKey = randomKey;
            }
            optionNew.put(randomKey,option.get(next));
        }

        return new Topic(optionNew,newKey);
    }


}

5.数据初始化(访问类:使用考卷实例questionBank进行复制克隆新的对象方法)

及main方法测试

import com.alibaba.fastjson.JSON;

import java.util.HashMap;
import java.util.Map;

/**
 * 初始化学生试卷数据
 */
public class QuestionBankInit {

    private QuestionBank questionBank = new QuestionBank();

    public QuestionBankInit(){
        Map<String,String> map1 = new HashMap<>();
        map1.put("A","Java");
        map1.put("B","python");
        map1.put("C","C++");
        map1.put("D","php");
        Map<String,String> map2 = new HashMap<>();
        map2.put("A","狗");
        map2.put("B","猫");
        map2.put("C","老鼠");
        map2.put("D","青蛙");
        Map<String,String> map3 = new HashMap<>();
        map3.put("A","乒乓球");
        map3.put("B","男足");
        map3.put("C","排球");
        map3.put("D","篮球");
        questionBank.append(new ChoiceQuestion("最好的开发语言是?",map1,"A"))
                    .append(new ChoiceQuestion("什么动物爱吃老鼠?",map2,"B"))
                    .append(new ChoiceQuestion("什么体育运动最伤中国人的心?",map3,"B"));
    }

    /**
     * 访问类:使用考卷实例questionBank进行复制克隆新的对象方法;
     */
    public String createPaper(String candidate,String number) throws CloneNotSupportedException{
        QuestionBank questionBankClone = (QuestionBank)questionBank.clone();
        questionBankClone.setCandidate(candidate);
        questionBankClone.setNumber(number);
        return JSON.toJSONString(questionBankClone);
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        QuestionBankInit questionBankInit = new QuestionBankInit();
        System.out.println(questionBankInit.createPaper("小明","001"));
        System.out.println(questionBankInit.createPaper("小张","002"));
        System.out.println(questionBankInit.createPaper("小杨","003"));
    }

}

查看执行结果:从结果中我们看到,不同学生的选择题及选项的顺序都是不一样的,达到了混排的目的,到此就演示结束了;

 

版权声明:以上代码示例参考《重学JAVA设计模式》一书。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值