设计模式-原型模式

来源:互联网 发布:收费软件 编辑:程序博客网 时间:2024/05/21 10:57

概述

在平常的开发过程中,有时我们会需要重复创建很多个同类型的对象实例。当对象的创建过程比较复杂和耗时的时候,这种重复创建的开销是很大的。为了降低系统压力,提升系统性能,可以考虑使用原型模式。

定义

定义一个原型实例指定对象种类,并通过拷贝创建新的实例。

模式类图如下:
原型模式

Java实现

抽象原型

public class Prototype implements Cloneable {    public Prototype clone() {        Object obj = null;        try {            obj = super.clone();            return (Prototype) obj;        } catch (CloneNotSupportedException e) {            e.printStackTrace();            return null;        }    }}

具体原型

public class ConcretePrototype extends Prototype {    public void doSomething() {    }}

客户端

public class Client {    public static void main(String[] args) {        Prototype prototype = new Prototype();        Prototype prototype_new = prototype.clone();        System.out.println("对象是否相同:" + (prototype == prototype_new));    }}

注意事项

这里要注意的主要是深克隆和浅克隆的问题,我们先来看一下深克隆和浅克隆的区别吧。在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。而在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。如图所示:

深克隆和浅克隆的区别

在Java语言中,因为所有的对象都继承自java.lang.Object,所以所有对象天生就可以使用clone()方法来实现克隆,但是Object类的clone()方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,而只会拷贝指向对象的引用。因此,要实现深拷贝,必须将这些对象另行拷贝。

public class Prototype implements Cloneable {    private ArrayList list = new ArrayList();    public Prototype clone() {        Prototype prototype = null;        try {            prototype = (Prototype) super.clone();            prototype.list = (ArrayList) this.list.clone();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return prototype;    }}

另外,当包含自定义引用类型成员变量的原型类想要实现深克隆时,Object类的clone()方法就无能为力了,这时我们就可以通过序列化(Serialization)的方式来实现深克隆。

public class Prototype implements Cloneable, Serializable {    // 自定义引用类型成员变量,必须实现序列化接口    Address address = new Address();    public Prototype clone() {        Prototype prototype = null;        try {            // 将对象写入流中            ByteArrayOutputStream bao = new ByteArrayOutputStream();            ObjectOutputStream oos = new ObjectOutputStream(bao);            oos.writeObject(this);            // 将对象从流中取出            ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray());            ObjectInputStream ois = new ObjectInputStream(bai);            prototype = (Prototype) ois.readObject();        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        return prototype;    }}

总结

当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过拷贝现有实例可以提高新实例的创建效率。(Object类的clone()方法调用的是本地方法)

原创粉丝点击