什么是原型模式

原型模式(Prototype Pattern)是五种创建型模式的其中一种,用原型实例指定创建对象的种类作为原型,并且通过拷贝原型来创建新的对象。

为什么要使用原型模式

新建一个对象有时候会很麻烦,可能涉及大量的变量初始化,函数、代码块的执行,不仅浪费资源,还会涉及数据准备、访问权限等操作。

实现

原型模式至少涉及两个角色:

  • Prototype,即原型类:需要实现Cloneable接口,并重写clone()方法,为外部提供一个克隆自身的方法;
  • Client,即应用类:让一个原型克隆自身从而创建一个新的对象。
public class Prototype implements Cloneable {//自身的一些方法...@Overridepublic Object clone() throws CloneNotSupportedException {Prototype proto = (Prototype) super.clone();return proto;}
}
public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();Prototype prototype1 = (Prototype) prototype.clone();...}
}

为了探讨其中的一些细节,我们对上面的代码稍微添加一些细节部分:

public class Prototype implements Cloneable {private String name;public Prototype() {System.out.println("empty constructor--------------------");}public Prototype(String name) {System.out.println("constructor--------------------");this.name = name;}@Overridepublic Object clone() throws CloneNotSupportedException {Prototype proto = (Prototype) super.clone();return proto;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return super.toString() + " " + this.getName();}
}public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();prototype.setName("111");System.out.println(prototype.toString());Prototype prototype1 = (Prototype) prototype.clone();System.out.println(prototype1.toString());prototype1.setName("222");System.out.println(prototype.toString());System.out.println(prototype1.toString());}
}

在Prototype类中加入了构造函数,重写了toString(),运行main(),结果如下:

empty constructor--------------------
com.company.Prototype@4554617c 111
com.company.Prototype@74a14482 111
com.company.Prototype@4554617c 111
com.company.Prototype@74a14482 222

可以看出:

构造函数只执行了一次,说明复制原型类的对象并不需要执行构造函数;
原对象和复制对象的地址不同,说明是重新创建的;
目前看来,在复制完成之后,复制的对象似乎和原对象就没有关系了,原对象的改变不会影响复制的对象,复制的对象改变也不会影响原对象。

真的是这样吗?

我们修改一下代码:

public class Car {private String color;public Car() {}public Car(String color) {this.color = color;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}
}public class Prototype implements Cloneable {private String name;private Car car;public Prototype() {System.out.println("empty constructor--------------------");}public Prototype(String name) {System.out.println("constructor--------------------");this.name = name;}public Prototype(String name, Car car) {this.name = name;this.car = car;}@Overridepublic Object clone() throws CloneNotSupportedException {Prototype proto = (Prototype) super.clone();return proto;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return super.toString() + " " + this.getName() + " " + this.getCar().getColor() + " Car" +  " " + this.getCar().toString();}
}public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();Car car1 = new Car("red");Car car2 = new Car("yel");prototype.setName("111");prototype.setCar(car1);System.out.println(prototype.toString());Prototype prototype1 = (Prototype) prototype.clone();System.out.println(prototype1.toString());prototype1.setName("222");prototype1.setCar(car2);System.out.println(prototype.toString());System.out.println(prototype1.toString());}
}

执行结果:

empty constructor--------------------
com.company.Prototype@4554617c 111 red Car com.company.Car@74a14482
com.company.Prototype@1540e19d 111 red Car com.company.Car@74a14482
com.company.Prototype@4554617c 111 red Car com.company.Car@74a14482
com.company.Prototype@1540e19d 222 yel Car com.company.Car@677327b6

可以看过结果中第4行和第5行,Car的颜色和地址都不一样,我几乎可以得出结论它们确实不是一个对象了,但是这样写其实是有漏洞的,我通过setCar()是显式地改变了这个对象,不能正确得出结论。

再将输出改一下:

public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();Car car1 = new Car("red");prototype.setName("111");prototype.setCar(car1);System.out.println(prototype.toString());Prototype prototype1 = (Prototype) prototype.clone();System.out.println(prototype1.toString());prototype1.setName("222");prototype1.getCar().setColor("black");System.out.println(prototype.toString());System.out.println(prototype1.toString());}
}

结果变为:

empty constructor--------------------
com.company.Prototype@4554617c 111 red Car com.company.Car@74a14482
com.company.Prototype@1540e19d 111 red Car com.company.Car@74a14482
com.company.Prototype@4554617c 111 black Car com.company.Car@74a14482
com.company.Prototype@1540e19d 222 black Car com.company.Car@74a14482

所有的Car对象的地址都是同一个,颜色值也一同改变,说明clone()实现的是浅拷贝。

浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型仍指向的还是原对象所指向的地址。 深复制:将一个对象复制后,基本数据类型和引用类型都重新创建。

如果想对引用类型也实现深拷贝,可以采用二进制流读写等操作实现,此处不再详述。

小唐说设计模式————原型模式相关推荐

  1. 小唐说设计模式————策略模式篇

    策略模式适用于什么样子的场景呢?     当我们的代码中出现了一连串的if-else-或者是switch-case-语句时,我们的代码体就会很长很臃肿,阅读性大大下降,此时可采用策略模式进行重构. 原 ...

  2. 设计模式 原型模式_创新设计模式:原型模式

    设计模式 原型模式 原型模式用于创建对象的副本. 这种模式非常有用,特别是当从头开始创建对象的成本很高时. 与builder , factory和abstract factory模式相比,它不会从头开 ...

  3. 设计模式 原型模式_设计模式:原型

    设计模式 原型模式 创新设计模式之一是原型设计模式 . 尽管原型是创造模式,但它在概念上与其他模式有所区别. 我的意思是原型在某种意义上创造了自己. 我将在下面解释. 原型模式的所有魔力都基于Java ...

  4. 设计模式 原型模式_原型设计模式:创建另一个小车

    设计模式 原型模式 创建对象确实是一个耗时的过程,也是一件昂贵的事情. 因此,我们现在正冒险节省时间和金钱. 我们该怎么做? 克隆奇迹多莉 有人记得多莉吗? 是的,是绵羊,是第一个被克隆的哺乳动物. ...

  5. Java常用设计模式————原型模式(一)

    介绍 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 原型模式用于创建重复的对象,同时又能保证性能.当直接创建对象的代价比较大时,则采用 ...

  6. 第六章 Caché 设计模式 原型模式

    文章目录 第六章 Caché 设计模式 原型模式 定义 使用场景 优点 结构图 描述 示例 初级写法 缺点 中级写法 缺点 高级写法 (浅复制) 浅复制 深复制 完整示例 简历类(复制类) 对象类(工 ...

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

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

  8. Python设计模式——原型模式

    原型模式(Protoype) 也可以称为复制模式.用原型模式,本质就是克隆对象,所以在对象初始化操作比较复杂的情况下,很实用,这既隐藏了对象创建的细节,又能大大降低耗时,提高性能. 目的: 原型模式用 ...

  9. Java设计模式——原型模式

    概述 原型模式是为了解决一些不必要的对象创建过程.当Java JDK中提供了Cloneable接口之后,原型模式就变得异常的简单了.虽然由于Cloneable的引入使用程序变得更简单了,不过还是有一些 ...

最新文章

  1. 论坛报名 | 与联合国、世卫组织等专家共话人工智能伦理与可持续发展
  2. 《研磨设计模式》chap12 观察者模式observer(2)模式介绍
  3. 02_pandas获取数据(指定列获取、[]方式获取、loc函数,at函数, iloc函数 iat函数)
  4. 年后来广州第一天,写篇水文
  5. jmeter对乱码如何处理_JMeter读取 Excel 表中用例数据实现接口压测
  6. 分布式事物框架TCC-Transaction使用教程
  7. Vue学习笔记(三) —— 前后端交互
  8. JAVA简单的SWING及AWT
  9. 用winformz时间格式不正确_巨峰葡萄不能膨大?错!在正确的时间,用对方法,收获优质果穗型...
  10. zb_system login.php,zblog后台登录地址怎么修改?
  11. 使用python构建基于hadoop的mapreduce日志分析平台
  12. 分析 2017年淘宝天猫活动时间安排
  13. 使用Hooks实现防抖节流 TS版本
  14. Idea如何设置类头注释(图片步骤直接到位)
  15. 安装webase时报错,Nginx冲突!
  16. keepalived结合nginx主备高可用实现
  17. 全球时区(查询备用)
  18. asc速度慢 mysql_按desc排序的mysql速度很快,但asc速度很慢
  19. 记一次网络风暴/网络环路
  20. Qmsg酱实现QQ消息自由推送

热门文章

  1. 微信h5更新服务器 用户不更新,微信网页授权token刷新和缓存问题
  2. TensorFlow模型构建(过拟合和欠拟合)三
  3. 课程总结:我们学到了什么?
  4. 生产管理电子看板,打造目视化精益工厂
  5. centos7.6安装git
  6. java使用ews-java-api发送邮件(包括附件和内联图片处理)
  7. 大数据信息资料采集:喜马拉雅电台音频节目FM有声小说听书采集
  8. 2021年电工(初级)考试总结及电工(初级)模拟考试系统
  9. invariant 释义
  10. OpenGL ES2.0 – Iphone开发指引