设计模式--原型模式

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

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

适用场景:

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

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

3、构造函数比较复杂

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

其中对象的JSON化处理,也是一种原型模式。

@Data
public class ConcreatePrototype implements Cloneable,Serializable {

    private int age;

    private String name;

    private List<String> hobbies;

    /*
    这个方法是浅拷贝,拷贝数据,不拷贝引用,上面的list集合就没有拷贝,拷贝后的对象的
    集合是指向相同的内存空间
     */
    @Override
    protected ConcreatePrototype clone() {
        try {
            return (ConcreatePrototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    /*
    这个方法是深拷贝,拷贝地址,上面的list集合,会拷贝出一个相同内容的数据地址,但对新的内存地址的操作,不会影响到
    原来内存的数据
     */
    public ConcreatePrototype deepClone() {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(outputStream);
            oos.writeObject(this);

            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            ObjectInputStream ios = new ObjectInputStream(inputStream);
            return (ConcreatePrototype) ios.readObject();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


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

克隆破坏单例

如果克隆对象是单例对象。那么,深克隆就会破坏单例,我们可以通过禁止克隆:例如不实现Cloneable接口;要么重写clone()方法,在克隆中返回单例对象。

@Override
protected Object clone() throws CloneNotSupportedException {
    return LazyHolder.LAZY;
}

原型模式在源码中的应用

ArrayList类的实现

public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

这其实是硬编码的方式,如果对象中申明了很多种集合类型,都要针对每种情况进行单独处理。所以深克隆都采用序列化的方式来操作。

原型模式的优缺点:

优点:

1.性能优良,Java自带的原型模式是基于内存二进制流的拷贝,比直接new一个对象性能上提升了许多。

2、可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到某一历史状态),可辅助实现撤销操作。

缺点:

1、需要为每一个类配置一个克隆方法。

2、克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。

3、在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多种嵌套引用时,为了实现深拷贝,每一层对象对应的类都必须支持深克隆,实现起来比较麻烦。

因此,深拷贝、浅拷贝需要根据场景来使用。

代码链接

原型模式

posted @ 2021-04-22 22:27  snail灬  阅读(80)  评论(0编辑  收藏  举报