图片

在 Java 中,我们可以使用 new 关键字指定类名来生成类的实例。但是,有的时候,我们也会在不指定类名的前提下生成实例,例如像图形编辑器中拖动现有的模型工具制作图形的实例,这种是非常典型的生成实例的过程太过复杂,很难根据类来生成实例场景,因此需要根据现有的实例来生成新的实例。

像这样根据实例来生成新的实例的模式,我们称之为 原型模式

在软件开发过程中,我们经常会遇到需要创建多个相同或者相似对象的情况,因此 原型模式 的使用频率还是很高的。

如何理解原型模式

在原型模式中涉及 Prototype、 ConcretePrototype、 Client 三个角色。图片

Prototype - 抽象原型类

Prototype,即抽象原型类。声明一个 clone 自己的方法,是所有具体原型类的公共父类,可以是抽象类或者是接口,甚至还可以是具体实现类。

图片

ConcretePrototype - 具体原型类

ConcretePrototype, 即具体原型类。实现 clone 自己的实例并生成新的实例的方法。

图片

Client - 客户类

负责使用复制实例的方法生成新的实例。客户类基于接口编程,用户可以根据需要选择具体原型类,系统具有较好的可扩展性。

图片

简要定义

使用原型实例指定创建对象的种类,并且拷贝这个原型来创建新的对象。

Java 的原型模式

Java 中使用原型模式很简单, 它为我们提供了复制实例的 clone() 方法。

实际上,所有的 Java 类都继承自 java.lang.Object。Object 类提供一个 clone() 方法,因此,在 Java 中可以直接使用 Object 提供的 clone() 方法来实现对象的克隆。

值得注意的是,被复制对象的类必须实现 java.lang.Cloneable 接口,如果没有实现 java.lang.Cloneable 接口的实例调用了 clone() 方法,会在运行时抛出 CloneNotSupportedException 异常。

Cloneable 是一个标记接口,在 Cloneable 接口中并没有声明任何方法,它只是被用来标记可以使用 clone() 方法进行复制。

图片

案例分析

现在,我有一个日报系统的需求,希望复制原先的日报内容进行快速创建,然后可以进行修改后保存。

下面,我们通过 Java 的 clone()方法来实现对象的克隆。

DailyModel 就是具体原型类,复制实现 clone() 方法。

图片

客户类负责使用复制实例的方法生成新的实例。

图片

思维发散

原型模式 vs 根据类创建实例

既然要创建新的实例,为什么不直接使用 new XXX(),而要设计出一个原型模式进行实例的复制呢?

有的时候,我们也会在不指定类名的前提下生成实例,例如像图形编辑器中拖动现有的模型工具制作图形的实例,这种是非常典型的生成实例的过程太过复杂,很难根据类来生成实例场景,因此需要根据现有的实例来生成新的实例。

还比如,类初始化需要消化非常多的资源,我们也可以考虑使用原型模式。因为,原型模式是在内存进行二进制流的拷贝,要比直接 new 一个对象性能好很多。

原型模式创建的对象是全新的对象吗

原型模式通过 clone() 方法创建的对象是全新的对象,它在内存中拥有新的地址。

浅克隆 vs 深克隆

clone() 方法使用的是浅克隆。浅克隆对于要克隆的对象, 会复制其基本数据类型和 String 类型的属性的值给新的对象. 而对于非基本数据类型的属性,例如数组、集合, 仅仅复制一份引用给新产生的对象, 即新产生的对象和原始对象中的非基本数据类型的属性都指向的是同一个对象。

此外,还存在深克隆。深克隆对于要克隆的对象, 对于非基本数据类型的属性,例如数组、集合支持复制。换句话说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

浅克隆和深克隆的主要区别在于,是否支持引用类型的成员变量的复制。

在 Java 中,如果需要实现深克隆,可以通过序列化等方式来实现。

图片

图片

图片

总结

原型模式的目的在于,根据实例来生成新的实例,我们可以很方便的快速的创建实例。

在 Java 中使用原型模式很简单, 被复制对象的类必须实现 java.lang.Cloneable 接口,并重写 clone() 方法。

使用原型模式的时候,尤其需要注意浅克隆和深克隆问题。在 Java 中,如果需要实现深克隆,可以通过序列化等方式来实现。

示例代码: https://github.com/lianggzone/design-pattern-action


更多相关文章

  1. 单例模式 - 只有一个实例
  2. Tomcat 单机多实例部署
  3. jQuery的DOM操作实例(3)——创建节点&&编写一个弹窗
  4. 开发学习Jquery实例---双击表格弹出模态对话框,编辑提交数据
  5. Kendo网格:以角度获取小部件实例
  6. jQuery实例:输入框下拉提示,仿google suggest
  7. jQuery实例(ajax通信和动态加载二级菜单)
  8. jQuery File Upload 单页面多实例的实现
  9. 百度地图Api进阶教程-实例高级操作8.html

随机推荐

  1. 全文检索引擎 Solr 系列(3)— Solr 核心概
  2. 浅谈easy-mock 最好的备胎没有之一
  3. 谁要是再敢用Map传参,我过去就是一JIO
  4. 不瞒你说,我最近跟Java源码杠上了
  5. 听说程序猿不会撩妹,我笑了
  6. immutability-helper因React官方出镜,而被
  7. 万圣节带你一起去鬼混!
  8. webpack4配置详解之常用插件分享
  9. 全民抵制“辱华”品牌秀,D&G神回复:呵呵~ 那
  10. 面对裁员,你还敢说老了真学不动了吗?