美文网首页
原型模式

原型模式

作者: Jackson杰 | 来源:发表于2019-01-03 14:41 被阅读0次

一 定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式也是一种创建型模式,不同的是,新对象的创建不是通过new来创建,而是在有一个原型对象的基础上通过克隆的方式,快速生成一个和原对象一样的实例。

二 使用场景

  • 资源优化:当类的初始化需要消耗非常多的资源时,这个资源包括数据资源,硬件资源等。
  • 性能和安全要求:通过new产生一个对象需要非常繁琐的数据准备和访问权限。
  • 一个对象,多个修改者:一个对象需要提供给其它对象访问,而且各个调用者可能都要修改其值时。

三 模式结构

  • Client:客户端用户
  • Prototype:抽象类或者接口,声明具备clone能力
  • ConcretePrototype:具体的原型类

四 实例

定义一个类,实现简历的功能,然后通过复制的方式,复制简历。

public class Resume implements Cloneable {

    private String name;
    private String birthday;
    private String school;

    /**
     * 构造方法
     * @param name
     */
    public Resume(String name) {
        this.name = name;
    }

    public void setPersonInfo(String birthday, String school) {
        this.birthday = birthday;
        this.school = school;
    }

    public void display(){
        System.out.println("姓名:"+name);
        System.out.println("生日:"+birthday+" 毕业院校:"+school);
    }

    /**
     * 克隆该实例
     * @return
     */
   @Override
    protected Object clone(){
        Resume resume=null;

        try {
            resume= (Resume) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return resume;
    }

}

客户端测试

 Resume resume1=new Resume("Jackson");
        resume1.setPersonInfo("1990-05-23","华中科技大学");

        Resume resume2= (Resume) resume1.clone();

        System.out.println("-------------------- resume1 ----------------------");
        resume1.display();
        System.out.println("-------------------- resume2 ----------------------");
        resume2.display();

浅拷贝和深拷贝

运用原型模式,实际上只是一个浅拷贝,该拷贝并不是将原始文档上的所有字段都重新构造了一份,而是拷贝文档的字段对原始文档字段的引用。
我们在上面代码加一个字段,设置公司的网列表。

public class Resume implements Cloneable {

    private String name;
    private String birthday;
    private String school;

    private List<String> company=new ArrayList<>();

   /**
     * 添加公司
     * @param company
     */
    public void addCompany(String company){
        this.company.add(company);
    }


    public void display(){
        System.out.println("姓名:"+name);
        System.out.println("生日:"+birthday+" 毕业院校:"+school);
        for (String company:company){
            System.out.println("company:"+company);
        }
    }

    /**
     * 克隆该实例
     * @return
     */
    @Override
    protected Object clone(){
        Resume resume=null;

        try {
            resume= (Resume) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return resume;
    }


    public String getName() {
        return name;
    }

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

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    public List<String> getCompany() {
        return company;
    }

    public void setCompany(List<String> company) {
        this.company = company;
    }
}

客户端代码如下

 Resume resume1=new Resume();
        resume1.setName("Jackson");
        resume1.setBirthday("1990-05-23");
        resume1.setSchool("华中科技大学");
        resume1.addCompany("腾讯");
        resume1.addCompany("阿里巴巴");
        resume1.addCompany("百度");


        Resume resume2= (Resume) resume1.clone();
        resume2.setName("Lucy");
        resume2.setBirthday("1992-05-17");
        resume2.setSchool("华东师范大学");

        resume2.addCompany("小米");


        System.out.println("-------------------- resume1 ----------------------");
        resume1.display();
        System.out.println("-------------------- resume2 ----------------------");
        resume2.display();

我们在resume2里添加了小米,如果是深拷贝,resume1里应该不会有小米。
运行代码结果如下:



从结果可以看到,resume1里出现了小米,说明修改了拷贝,原数据也修改了,对于List<String> company,拷贝数据只是原始数据的引用。

深拷贝
修改clone()代码如下,对浅拷贝的ArrayList<String> company也调用clone()方法。

 /**
     * 克隆该实例
     * @return
     */
    @Override
    protected Object clone(){
        Resume resume=null;

        try {
            resume= (Resume) super.clone();
            // 对List<String> company对象也调用clone()
            resume.company=(ArrayList<String>)this.company.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return resume;
    }

运行结果如下:



可以看到,resume1中已经没有了小米。
原型模式比较简单,比直接new一个对象要方便多了,特别是要在一个循环体中产生大量对象时。
但是,一定要注意,在拷贝过程中,构造方法是不会执行的。

相关文章

  • 第3章 创建型模式-原型模式

    一、原型模式简介 二、原型模式的优点 ■ 三、原型模式的使用场景 ■ 四、原型模式的实例

  • 设计模式之原型模式(Prototype 模式)

    引入原型模式 原型模式的实例 为什么需要使用原型模式 引入原型模式 如果读者很熟悉javascript的话,对原型...

  • 初始设计模式之原型模式

    原型模式是什么? 原型模式怎么用?浅拷贝深拷贝 原型模式再理解 一、原型模式是什么? ​ 原型模式是一种创建型设计...

  • 设计模式之原型模式(创建型)

    [TOC] 模式定义 原型模式(Prototype Pattern):原型模式是提供一个原型接口,提供原型的克隆,...

  • 原型模式C++

    原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式结构图 原型模式基本代码 原型...

  • 设计模式:原型

    原型模式基本介绍原型模式的实现源码中的原型模式记录 原型模式基本介绍 定义:用原型实例指定创建对象的种类,并通过复...

  • js集成

    原始继承模式--原型链 2:借用构造函数 3:共享构造原型 4:圣杯模式原型链; 构造函数; 共享原型; 圣杯模式...

  • 关于JavaScript创建对象的多种方式

    JavaScript创建对象的方法 工厂模式 构造函数模式 原型模式 组合使用构造函数模式和原型模式 动态原型模式...

  • 前端面试题总结【37】:javascript对象的几种创建方式

    工厂模式 构造函数模式 原型模式 混合构造函数和原型模式 动态原型模式 寄生构造函数模式 稳妥构造函数模式 推荐:...

  • 设计模式之原型模式

    原型模式 原型模式(prototype)是指原型实例指向对象的种类,并且通过拷贝这些原型创建新的对象 模式作用: ...

网友评论

      本文标题:原型模式

      本文链接:https://www.haomeiwen.com/subject/qmiclqtx.html