首先对原型模式进行一个简单概念说明:通过一个已经存在的对象,复制出更多的具有与此对象具有相同类型的新的对象。

在理解Java原型模式之前,首先需要理解Java中的一个概念:复制/克隆。

在博文《Java总结篇系列:java.lang.Object》一文中,对Java中的clone()方法进行了一定的阐述。同时,我们需要知道,Java中的对象复制/克隆分为浅复制和深复制。

一、浅复制:

我们知道,一个类的定义中包括属性和方法。属性用于表示对象的状态,方法用于表示对象所具有的行为。其中,属性既可以是Java中基本数据类型,也可以是引用类型。Java中的浅复制通常使用clone()方式完成。

当进浅复制时,clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。同时,复制出来的对象具有与原对象一致的状态。

此处对象一致的状态是指:复制出的对象与原对象中的属性值完全相等==。

下面以复制一本书为例:

1.定义Book类和Author类:

 1 class Author {
 2
 3     private String name;
 4     private int age;
 5
 6     public String getName() {
 7         return name;
 8     }
 9
10     public void setName(String name) {
11         this.name = name;
12     }
13
14     public int getAge() {
15         return age;
16     }
17
18     public void setAge(int age) {
19         this.age = age;
20     }
21
22 }

 1 class Book implements Cloneable {
 2
 3     private String title;
 4     private int pageNum;
 5     private Author author;
 6
 7     public Book clone() {
 8         Book book = null;
 9         try {
10             book = (Book) super.clone();
11         } catch (CloneNotSupportedException e) {
12             // TODO Auto-generated catch block
13             e.printStackTrace();
14         }
15         return book;
16     }
17
18     public String getTitle() {
19         return title;
20     }
21
22     public void setTitle(String title) {
23         this.title = title;
24     }
25
26     public int getPageNum() {
27         return pageNum;
28     }
29
30     public void setPageNum(int pageNum) {
31         this.pageNum = pageNum;
32     }
33
34     public Author getAuthor() {
35         return author;
36     }
37
38     public void setAuthor(Author author) {
39         this.author = author;
40     }
41
42 }

2.测试:

 1 package com.qqyumidi;
 2
 3 public class PrototypeTest {
 4
 5     public static void main(String[] args) {
 6         Book book1 = new Book();
 7         Author author = new Author();
 8         author.setName("corn");
 9         author.setAge(100);
10         book1.setAuthor(author);
11         book1.setTitle("好记性不如烂博客");
12         book1.setPageNum(230);
13
14         Book book2 = book1.clone();
15
16         System.out.println(book1 == book2);  // false
17         System.out.println(book1.getPageNum() == book2.getPageNum());   // true
18         System.out.println(book1.getTitle() == book2.getTitle());        // true
19         System.out.println(book1.getAuthor() == book2.getAuthor());        // true
20
21     }
22 }

由输出的结果可以验证说到的结论。由此我们发现:虽然复制出来的对象重新在堆上开辟了内存空间,但是,对象中各属性确保持相等。对于基本数据类型很好理解,但对于引用数据类型来说,则意味着此引用类型的属性所指向的对象本身是相同的, 并没有重新开辟内存空间存储。换句话说,引用类型的属性所指向的对象并没有复制。

由此,我们将其称之为浅复制。当复制后的对象的引用类型的属性所指向的对象也重新得以复制,此时,称之为深复制。

 

二、深复制:

 Java中的深复制一般是通过对象的序列化和反序列化得以实现。序列化时,需要实现Serializable接口。

下面还是以Book为例,看下深复制的一般实现过程:

1.定义Book类和Author类(注意:不仅Book类需要实现Serializable接口,Author同样也需要实现Serializable接口!!):

 1 class Author implements Serializable{
 2
 3     private String name;
 4     private int age;
 5
 6     public String getName() {
 7         return name;
 8     }
 9
10     public void setName(String name) {
11         this.name = name;
12     }
13
14     public int getAge() {
15         return age;
16     }
17
18     public void setAge(int age) {
19         this.age = age;
20     }
21
22 }

 1 class Book implements Serializable {
 2
 3     private String title;
 4     private int pageNum;
 5     private Author author;
 6
 7     public Book deepClone() throws IOException, ClassNotFoundException{
 8         // 写入当前对象的二进制流
 9         ByteArrayOutputStream bos = new ByteArrayOutputStream();
10         ObjectOutputStream oos = new ObjectOutputStream(bos);
11         oos.writeObject(this);
12
13         // 读出二进制流产生的新对象
14         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
15         ObjectInputStream ois = new ObjectInputStream(bis);
16         return (Book) ois.readObject();
17     }
18
19     public String getTitle() {
20         return title;
21     }
22
23     public void setTitle(String title) {
24         this.title = title;
25     }
26
27     public int getPageNum() {
28         return pageNum;
29     }
30
31     public void setPageNum(int pageNum) {
32         this.pageNum = pageNum;
33     }
34
35     public Author getAuthor() {
36         return author;
37     }
38
39     public void setAuthor(Author author) {
40         this.author = author;
41     }
42
43 }

2.测试:

 1 public class PrototypeTest {
 2
 3     public static void main(String[] args) throws ClassNotFoundException, IOException {
 4         Book book1 = new Book();
 5         Author author = new Author();
 6         author.setName("corn");
 7         author.setAge(100);
 8         book1.setAuthor(author);
 9         book1.setTitle("好记性不如烂博客");
10         book1.setPageNum(230);
11
12         Book book2 = book1.deepClone();
13
14         System.out.println(book1 == book2);  // false
15         System.out.println(book1.getPageNum() == book2.getPageNum());   // true
16         System.out.println(book1.getTitle() == book2.getTitle());        // false
17         System.out.println(book1.getAuthor() == book2.getAuthor());        // false
18
19     }
20 }

从输出结果中可以看出,深复制不仅在堆内存上开辟了空间以存储复制出的对象,甚至连对象中的引用类型的属性所指向的对象也得以复制,重新开辟了堆空间存储。

至此:设计模式中的创建型模式总结完毕,一共有五种创建型模式,分别为:单例模式(SingleTon)、建造者模式(Builder)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)和原型模式(Prototype)。每种模式适用于不同的场景,具体应用时需注意区分。

设计模式总结篇系列:原型模式(Prototype)相关推荐

  1. 跟着实例学习设计模式(7)-原型模式prototype(创建型)

    原型模式是创建型模式. 设计意图:用原型实例指定创建对象的类型,并通过拷贝这个原型来创建新的对象. 我们使用构建简历的样例的类图来说明原型模式. 类图: 原型模式主要用于对象的复制.它的核心是就是类图 ...

  2. 设计模式(三)原型模式 Prototype

    原型模式 原型模式概念 适用场景 简单克隆 浅克隆 深克隆 破坏单例 开源工具 总结 原型模式概念 原型模式(Prototype Pattern)是指原型实例指定创建对象的 种类,并且通过拷贝这些原型 ...

  3. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    [索引页] [源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:webabcd 介绍 用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象. ...

  4. C++设计模式——原型模式(Prototype Pattern)

    C++设计模式--原型模式(Prototype Pattern) 微信公众号:幼儿园的学霸 目录 文章目录 C++设计模式--原型模式(Prototype Pattern) 目录 定义 代码示例 普通 ...

  5. 设计模式(23):创建型-原型模式(Prototype)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

  6. Java设计模式--原型模式Prototype

    原型模式Prototype 原型模式使得用户可以通过复制对象样本来创建新对象.与通过调用构造函数创建对象相比,二者主要区别在于:通过复制创建的新对象一般会包含原始对象的某些状态. 原型模式属于对象的创 ...

  7. 设计模式(五)—— 原型模式(定义、案例分析、特点、缺点)

    文章目录 前言 正文 一.定义 二.模式结构及分析 (一) 模式结构 (二) 模式分析 三.情景假设 四.情景分析 (一) 浅克隆 (二) 深克隆 五.模式优点.缺点 (一)模式优点 (二)模式缺点 ...

  8. 原型模式(ProtoType) - Java里的对象复制

    一, 引用的复制和对象复制. 在编程中, 我们有时会用两个引用指向同一个对象. 例如: ArrayList a = new ArrayLIst(); ArrayList b = a; 看起来好像有a, ...

  9. 原型模式(Prototype Pattern)

    原型模式(Prototype Pattern) 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. ...

  10. 从真实项目中抠出来的设计模式——第二篇:过滤器模式

    一:实际场景介绍 我们在给用户做订单催付通知的时候,会有这样的一种场景,用户在系统后台设置一组可以催付的规则,比如说订单金额大于xx元,非黑名单用户,来自 哪个地区,已购买过某个商品,指定某个营销活动 ...

最新文章

  1. iOS 11开发教程(七)编写第一个iOS11代码Hello,World
  2. 学校APP太难用,码农爸妈们自己做出开源程序,官方却要报警
  3. PHP (20140519)
  4. php 工厂模式 使用场景,PHP设计模式之工厂模式
  5. 不能用蛮力法解决的问题_溆浦事蒙汉:脱贫攻坚绝不能心浮气躁骄傲自满疲倦厌战...
  6. 运行第一个 docker image 并在浏览器中查看
  7. 7-69 计算圆周率 (15 分)
  8. mysql客户端不支持_MySQL 8.0 - 客户端不支持服务器请求的身份验证协议; 考虑升级MySQL客户端...
  9. java hbase 例子,java操作hbase例子
  10. ubuntu 16.04 创建新用户
  11. 《大规模元搜索引擎技(1)》一 2.1 系统体系结构
  12. floodlight路由机制分析
  13. 基于系统的软件测试报告,软件系统测试报告模板.doc
  14. win系统分区表丢失后如何恢复
  15. Bacnet协议/Bacnet4j读写
  16. 多多情报通:拼多多什么软件可以看到大数据?拼多多大数据分析软件有哪些?
  17. 黑马程序员--技术网站网址2
  18. 微信小程序|考试系统|基于微信小程序和SpringBoot+VUE的智能在线考试系统毕业设计
  19. php-tanita,♥【停更】 ♥【 鉴于有些人把分享了的二次分享到别的论坛在此停更】♥♥【Tanitas8专贴】♥♥...
  20. PMP证书备考攻略+PMP知识点汇总

热门文章

  1. oracle sql判断值为空,Oracle,sqlserver的空值(null)判断
  2. 压力传感器变送器读取数据测试:MIK-BSQW
  3. 转载:IDEA出现URI is not registered (Settings | Languages Frameworks | Schemas and DTDs)
  4. MySQL查询本年的数据的sql语句
  5. IDEA背景颜色设置护眼色
  6. oracle显示当天日期函数,oracle日期函数
  7. 图书管理系统python代码课程设计报告_数据结构图书管理系统课程设计报告
  8. fastcopy会损坏硬盘_电脑硬盘损坏如何修复?自己动手就能解决
  9. Emscripten 单词_初一(上)掌握这 4 大类发音规律,英语记单词很轻松
  10. bash 脚本的自解压流程