原型模式 与 建造者模式(1)

一、原型模式


原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,属于创建型模式。


原型模式的核心在于拷贝原型对象。以系统中已存在的一个对象为原型,直接基于内存二进制流进行拷贝,无需再经历耗时的对象初始化过程(不调用构造函数),性能提升许多。当兑现的构建过程比较耗时时,可以利用当前系统中已存在的对象作为原型,对其进行克隆(一般是基于二进制流的复制),躲避初始化过程,使得新对象的创建时间大大减少。下面,我们来看看原型模式类结构图。



原型模式 与 建造者模式(1)


从UML图中,我们可以看到,原型模式,主要包含三个角色:


客户(Client):客户类提出创建对象的请求。

抽象原型(Prototype):规定拷贝接口。

具体原型(Concrete Prototype):被拷贝的对象。

注:对不通过new关键字,而是通过对象拷贝来实现创建对象的模式就称作原型模式。


原型模式的应用场景

你一定遇到过大篇幅getter、setter赋值的场景。例如这样的代码:


@Data
public class ExamPaper{

   private String examinationPaperId;//试卷主键
   private String leavTime;//剩余时间
   private String organizationId;//单位主键
   private String id;//考试主键
   private String examRoomId;//考场主键
   private String userId;//用户主键
   private String specialtyCode;//专业代码
   private String postionCode;//报考岗位
   private String gradeCode;//报考等级
   private String examStartTime;//考试开始时间
   private String examEndTime;//考试结束时间
   private String singleSelectionImpCount;//单选选题重要数量
   private String multiSelectionImpCount;//多选题重要数量
   private String judgementImpCount;//判断题重要数量
   private String examTime;//考试时长
   private String fullScore;//总分
   private String passScore;//及格分
   private String userName;//学员姓名
   private String score;//考试得分
   private String resut;//是否及格
   private String singleOkCount;//单选题答对数量
   private String multiOkCount;//多选题答对数量
   private String judgementOkCount;//判断题答对数量

   public ExamPaper copy(){
      ExamPaper examPaper = new ExamPaper();
      //剩余时间
      examPaper.setLeavTime(this.getLeavTime());
      //单位主键
      examPaper.setOrganizationId(this.getOrganizationId());
      //考试主键
      examPaper.setId(this.getId());
      //用户主键
      examPaper.setUserId(this.getUserId());
      //专业
      examPaper.setSpecialtyCode(this.getSpecialtyCode());
      //岗位
      examPaper.setPostionCode(this.getPostionCode());
      //等级
      examPaper.setGradeCode(this.getGradeCode());
      //考试开始时间
      examPaper.setExamStartTime(this.getExamStartTime());
      //考试结束时间
      examPaper.setExamEndTime(this.getExamEndTime());
      //单选题重要数量
      examPaper.setSingleSelectionImpCount(this.getSingleSelectionImpCount());
      //多选题重要数量
      examPaper.setMultiSelectionImpCount(this.getMultiSelectionImpCount());
      //判断题重要数量
      examPaper.setJudgementImpCount(this.getJudgementImpCount());
      //考试时间
      examPaper.setExamTime(this.getExamTime());
      //总分
      examPaper.setFullScore(this.getFullScore());
      //及格分
      examPaper.setPassScore(this.getPassScore());
      //学员姓名
      examPaper.setUserName(this.getUserName());
      //分数
      examPaper.setScore(this.getScore());

      //单选答对数量
      examPaper.setSingleOkCount(this.getSingleOkCount());
      //多选答对数量
      examPaper.setMultiOkCount(this.getMultiOkCount());
      //判断答对数量
      examPaper.setJudgementOkCount(this.getJudgementOkCount());

      return examPaper;
   }

   @Override
   public String toString() {
      return "ExamPaper{" +
              "examinationPaperId='" + examinationPaperId + '\'' +
              ", leavTime='" + leavTime + '\'' +
              ", organizationId='" + organizationId + '\'' +
              ", id='" + id + '\'' +
              ", examRoomId='" + examRoomId + '\'' +
              ", userId='" + userId + '\'' +
              ", specialtyCode='" + specialtyCode + '\'' +
              ", postionCode='" + postionCode + '\'' +
              ", gradeCode='" + gradeCode + '\'' +
              ", examStartTime='" + examStartTime + '\'' +
              ", examEndTime='" + examEndTime + '\'' +
              ", singleSelectionImpCount='" + singleSelectionImpCount + '\'' +
              ", multiSelectionImpCount='" + multiSelectionImpCount + '\'' +
              ", judgementImpCount='" + judgementImpCount + '\'' +
              ", examTime='" + examTime + '\'' +
              ", fullScore='" + fullScore + '\'' +
              ", passScore='" + passScore + '\'' +
              ", userName='" + userName + '\'' +
              ", score='" + score + '\'' +
              ", resut='" + resut + '\'' +
              ", singleOkCount='" + singleOkCount + '\'' +
              ", multiOkCount='" + multiOkCount + '\'' +
              ", judgementOkCount='" + judgementOkCount + '\'' +
              '}';
   }
}


代码非常工整,命名非常规范,注释也写的很全面,其实这就是原型模式的需求场景。但是,上述代码属于纯体力劳动。那原型模式,能帮助我们解决这样的问题。


原型模式主要适用于以下场景:

1、类初始化消化资源较多

2、new 产生的一个对象需要非常繁琐的过程(数据准备,访问权限等)

3、构造函数比较复杂

4、循环体中生产大量的对象时。

在Spring中,原型模式应用得非常广泛。例如 scope = “prototype”,在我们经常用的JSON。parseObject()也是一种原型模式。


原型模式的通用写法


一个标准的原型模式代码,应该是这样设计的,先创建原型IPrototype接口:


public interface IPrototype<T> {
    T clone();
}


创建具体需要克隆的对象ConcretePrototype


public class ConcretePrototype implements IPrototype {

    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public ConcretePrototype clone() {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        concretePrototype.setAge(this.age);
        concretePrototype.setName(this.name);
        return concretePrototype;
    }

    @Override
    public String toString() {
        return "ConcretePrototype{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
上一篇:静态代理、动态代理(JDK动态代理,Cglib动态代理)(2)


下一篇:Git版本回退并且同步远端的记录