博客
关于我
java 原型模式(大话设计模式)
阅读量:665 次
发布时间:2019-03-16

本文共 5281 字,大约阅读时间需要 17 分钟。

原型模式(PrototypePattern)是一种经典的软件设计模式,其核心思想是利用原型实例来指定创建对象的类型,并通过复制这些原型来生成新的对象。这种模式非常适合对象的创造和复制场景,尤其在需要共享单元格或减少对象构造开销的时候表现优异。

浅拷贝(Shallow Copy)

浅拷贝是实现原型模式的基本方式。在浅拷贝中,新对象的每个成员字段都是直接引用原型对象的字段。也就是说,只有指针进行了复制,而不是拷贝数据。此时,原型对象的状态会直接影响新对象的状态,导致共享的单元格问题。下面是一个浅拷贝的例子:

public class WorkExperience {    private String workDate;    private String company;    // ... getter 和 setter 方法}
public class Resume implements Cloneable {    private String name;    private String sex;    private int age;    private WorkExperience workExperience;    public Resume(String name) {        this.name = name;        workExperience = new WorkExperience();    }    // ... setter 方法定义    @Override    public Object clone() throws CloneNotSupportedException {        return super.clone();    }}

客户端示例:

public class Client {    public static void main(String[] args) throws CloneNotSupportedException {        Resume r0 = new Resume("大鸟");        r0.setPersonalInfo("男", "29");        r0.setWorkExperience("1998-2000", "xx公司");        Resume r1 = (Resume) r0.clone();        r1.setWorkExperience("1998-2006", "yy企业");        Resume r2 = (Resume) r0.clone();        r2.setWorkExperience("1998-2003", "zz公司");        // 浅拷贝后的结果会共享同一工作经历对象        System.out.println("<-- 浅拷贝 -->");        r0.display();        r1.display();        r2.display();    }}

深拷贝(Deep Copy)

深拷贝是在浅拷贝的基础上,对每个引用字段进行深拷贝,确保新对象对其成员字段的引用是独立的。这个过程通常涉及序列化或反序列化,以确保所有相关对象都被正确拷贝。下面是一个深拷贝的实现示例:

public class WorkExperience {    private String workDate;    private String company;    // ...getter 和 setter 方法    @Override    public Object clone() throws CloneNotSupportedException {        return super.clone();    }}
public class Resume implements Cloneable {    private String name;    private String sex;    private int age;    private WorkExperience workExperience;    public Resume(String name) {        this.name = name;        this.workExperience = new WorkExperience();    }    public Resume(WorkExperience workExperience) throws CloneNotSupportedException {        this.workExperience = (WorkExperience) workExperience.clone();    }    // ... setter 方法定义    @Override    public Object clone() throws CloneNotSupportedException {        Resume resume = new Resume((WorkExperience) this.workExperience.clone());        resume.name = this.name;        resume.sex = this.sex;        resume.age = this.age;        return resume;    }}

客户端示例:

public class Client {    public static void main(String[] args) throws CloneNotSupportedException, IOException {        Resume r0 = new Resume("大鸟");        r0.setPersonalInfo("男", "29");        r0.setWorkExperience("1998-2000", "xx公司");        Resume r1 = (Resume) r0.clone();        r1.setWorkExperience("1998-2006", "yy公司");        Resume r2 = (Resume) r0.clone();        r2.setWorkExperience("1998-2003", "zz公司");        // 深拷贝后的每个对象都有独立的业务对象        System.out.println("<-- 深拷贝 -->");        r0.display();        r1.display();        r2.display();    }}

通过对象序列化实现深度拷贝

在某些情况下,特别是对象图结构较为复杂时,我们可以采用对象序列化的方式来实现深度拷贝。这种方法的优势在于其简单且适用于所有支持序列化的对象。以下是一个使用序列化实现深度拷贝的例子:

public class Resume implements Serializable {    private static final long serialVersionUID = -4410449301166191440L;    private String name;    private String sex;    private int age;    private WorkExperience workExperience;    public Resume() {        workExperience = new WorkExperience();    }    public void display() {        System.out.println("姓名:" + name + ",性别:" + sex + ",年龄:" + age +                          "\n工作经历:" + workExperience.getWorkDate() + "," + workExperience.getCompany());    }    public Object deepClone() throws IOException, ClassNotFoundException {        ByteArrayOutputStream bos = new ByteArrayOutputStream();        ObjectOutputStream oos = new ObjectOutputStream(bos);        oos.writeObject(this);        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());        ObjectInputStream ois = new ObjectInputStream(bis);        return ois.readObject();    }    // ... getter 和 setter 方法}

客户端示例:

public class PrototypeClient {    public static void shallowCopy() throws CloneNotSupportedException {        Resume aRes = new Resume("大鸟");        aRes.setPersonalInfo("男", "29");        aRes.setWorkExperience("1999-2002", "XX公司");        Resume bRes = (Resume) aRes.clone();        bRes.setWorkExperience("2001-2004", "YY公司");                System.out.println("浅拷贝结果:");        aRes.display();        bRes.display();    }    public static void deepCopy() throws CloneNotSupportedException, IOException, ClassNotFoundException {        Resume aRes = new Resume("大鸟");        aRes.setPersonalInfo("男", "29");        aRes.setWorkExperience("1999-2002", "XX公司");        Resume bRes = (Resume) aRes.deepClone();        bRes.setWorkExperience("2001-2004", "YY公司");        Resume cRes = (Resume) aRes.deepClone();        cRes.setWorkExperience("2003-2006", "ZZ公司");        System.out.println("深拷贝结果:");        aRes.display();        bRes.display();        cRes.display();    }    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {        shallowCopy();        System.out.println("==================================");        deepCopy();    }}

通过上述实现,我们可以清晰地看到浅拷贝和深拷贝的效果。浅拷贝在反射或序列化时可能导致内存泄漏或共享状态的问题,而深拷贝则确保了每个对象的独立性和完整性。选择何种拷贝方式取决于具体的应用场景和业务需求。

转载地址:http://ezmqz.baihongyu.com/

你可能感兴趣的文章
Failed to get D-Bus connection: Operation not permitted解决
查看>>
Oracle Orion tool check io(ORACLE Orion 工具查看以及校验IO)
查看>>
centos7一步一步搭建docker jenkins 及自定义访问路径重点讲解
查看>>
【Flink】Flink 底层RPC框架分析
查看>>
MySQL错误日志(Error Log)
查看>>
解决:angularjs radio默认选中失效问题
查看>>
windows环境下安装zookeeper(仅本地使用)
查看>>
缓冲区溢出实例(一)--Windows
查看>>
Hadoop学习笔记—Yarn
查看>>
Jenkins - 部署在Tomcat容器里的Jenkins,提示“反向代理设置有误”
查看>>
wxWidgets源码分析(3) - 消息映射表
查看>>
wxWidgets源码分析(5) - 窗口管理
查看>>
wxWidgets源码分析(8) - MVC架构
查看>>
wxWidgets源码分析(9) - wxString
查看>>
[梁山好汉说IT] 梁山好汉和抢劫银行
查看>>
[源码解析] 消息队列 Kombu 之 基本架构
查看>>
[源码分析] 消息队列 Kombu 之 启动过程
查看>>
wx.NET CLI wrapper for wxWidgets
查看>>
Silverlight for linux 和 DLR(Dynamic Language Runtime)
查看>>
ASP.NET MVC Action Filters
查看>>