简述

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口(在java中实现Cloneable),,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。还有在spring中的bean的scope中就有使用到原型模式。

原型模式的定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

原型模式的优点:

  1. java自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
  2. 可以使用深克隆保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用。

原型模式的缺点:

  1. 在java中需要为每一个类都配置一个 clone 方法
  2. clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
  3. 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来较麻烦(可以使用序列化和反序列化方式)。

原型模式的结构

原型模式包含以下主要角色。

  1. 抽象原型类:规定了具体原型对象必须实现的接口。
  2. 具体原型类:实现抽象原型类的 clone() 方法,它是被复制的对象。
  3. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

原型模式的克隆分为浅克隆和深克隆。

  • 浅克隆:创建一个新对象,新对象的属性和原来对象一样,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

 

uml类图

代码示例:

原型类代码 重点是实现Cloneable接口以及重写clone方法

package com.tianye.designModel.impl;

import java.io.*;

/**
 * @author 田野上的风筝
 * @version V1.0
 * @Description: TODO
 * @date 2020/12/2 10:37
 */
public class Prototype implements Cloneable, Serializable {

    private String name;
    private int age;
    private RefObject refObject;

    public Prototype(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public RefObject getRefObject() {
        return refObject;
    }

    public void setRefObject(RefObject refObject) {
        this.refObject = refObject;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    //重写克隆方法 默认浅拷贝
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Prototype clone = (Prototype) super.clone();
        return clone;
    }
   

    @Override
    public String toString() {
        return "Prototype{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", refObject=" + refObject +
                '}';
    }
}

客户端 main方法 使用

 public static void main(String[] args) throws CloneNotSupportedException {
        Prototype prototype = new Prototype("原型模板",2);
        prototype.setRefObject(new RefObject());
        Prototype clone1 = (Prototype) prototype.clone();
        Prototype clone2 = (Prototype) prototype.clone();
        System.out.println(clone1);
        System.out.println(clone2);
        System.out.println("原型 hashCode"+prototype.getRefObject().hashCode());
        System.out.println("浅克隆  hashCode"+clone1.getRefObject().hashCode());
        System.out.println("浅克隆  hashCode"+clone2.getRefObject().hashCode());
        System.out.println(prototype.getRefObject()==clone1.getRefObject());
        System.out.println(prototype.getRefObject()==clone2.getRefObject());
    }

运行mian方法,效果

上面使用的是浅克隆模式,下面使用深克隆模式,修改Prototype的clone方法

 //深拷贝 利用反序列 和序列化
    @Override
    protected Object clone() {
        //序列化 将当前对象序列化到内存中
        ByteArrayOutputStream byteArrayOutputStream;
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(byteArrayOutputStream);
            oos.writeObject(this);
            //反序列化
            byte[] bytes = byteArrayOutputStream.toByteArray();
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            ois = new ObjectInputStream(bis);
            return ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

运行效果

 

 

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐