三分钟理解“原型模式”——设计模式轻松掌握

原型模式的官方定义:

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

大白话:

现在有一个类,它要产生大量的对象,而且这些对象中的属性值大部分都相同;如果我们要获取这样一个对象的时候每次都通过new,然后再set每一个属性值,那么这样就太麻烦了。这种情况下使用原型模式非常便捷:

我们让这个类去实现ICloneable接口,并且实现该接口的clone()函数,在clone函数中让当前对象进行一次浅拷贝/深拷贝,总之就是克隆一个当前对象来,这样我们就无需new完了对象后再逐个set属性了。

原型模式的类图:

如果一个类要使得调用者能够克隆,那在定义这个类的时候就需要让它实现ICloneable接口,并实现clone函数,在函数中实现当前对象的浅拷贝或深拷贝。

客户端拿到这个类后,如果需要克隆对象,调用这个类的clone函数即可。

深拷贝和浅拷贝:

浅拷贝:将对象中基本数据类型的值复制到新的对象中去,若对象中有引用类型的属性,则将引用复制给新对象,此时,新旧对象中引用类型的指针都指向同一个对象。

如上图所示:新对象中的phone是基本数据类型,它的值是旧对象中直接复制过来的;而新对象中的Person是引用类型,它和旧对象中的Perosn都指向同一个Person对象。

深拷贝:深拷贝和浅拷贝对于基本数据类型都是一样复制,不同之处在于:浅拷贝之后新旧对象中的引用类型的变量都指向同一个对象,而深拷贝当遇到引用类型的对象时,再new一个对象,新对象中的引用类型变量指向新创建的对象,如下图所示:

使用深拷贝实现原型模式:

如上图所示,原型类中有引用类型的成员变量Person,并且Person类中有引用类型的成员变量Work,要实现深拷贝,要使得原型类、Person类、Work类中的clone函数都要实现深拷贝的功能,实现深拷贝的clone函数如下:

public Object clone(){

//将当前对象进行一次浅拷贝

原型 p = this.clone();

//将当前对象中引用类型的变量进行一次深拷贝。由于Person类也实现了ICloneable接口,并且clone函数也进行了一样的操作,调用Work类的clone函数,由于Work类中全都是基本数据类型,所以Work类不需要实现ICloneable接口,对Work类的克隆仅需要Object提供的clone()函数进行浅拷贝即可。

p.setPerson(this.person.clone());

return p;

}

Java中的clone函数:

Java中的Object类中就有clone()函数,并且这个函数是对对象进行浅拷贝。当我们需要对一个对象进行深拷贝的时候,就必须要让这个类实现Cloneable接口,并且重写clone()函数。

Java中的深拷贝和浅拷贝请移步至:http://blog.csdn.net/shootyou/article/details/3945221

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术专栏

Scala入门与进阶(六)- Scala 函数高级操作

822
来自专栏java一日一条

JavaScript 中 this 的使用技巧总结

在 js 中,this 这个上下文总是变化莫测,很多时候出现 bug 总是一头雾水,其实,只要分清楚不同的情况下如何执行就 ok 了。

443
来自专栏我的技术专栏

java与C++变量初始化的对比

863
来自专栏coder修行路

一篇文章让你明白python的装饰器

在看闭包问题之前先来看看关于python中作用域的问题 变量作用域 ? 对于上述代码中出现错误,肯定没什么疑问了,毕竟b并没有定义和赋值,当我们把代码更改如下后...

1911
来自专栏mathor

比较器Comparator

 java中有内置的排序,Arrays.sort(),现在我有一个Student类,类中三个成员变量name,id,age,我现在想以age作为参考进行升序排序...

522
来自专栏Golang语言社区

【Golang语言社区】前端编程-javascript使用闭包模拟私有属性和方法

最近因为做了一个项目,其中涉及到了js私有方法,这个概念在其语言里面是很常见的,很多语言都有private这个关键字,只要在一个类的前面加上private就表示...

2829
来自专栏码云1024

C# ref与out

2595
来自专栏吾爱乐享

java之学习Integer类相关面试题

1144
来自专栏技术博客

C#基础知识系列六(静态类和静态类成员)

  静态类与非静态类基本相同,但存在一个区别:静态类不能实例化。 也就是说,不能使用 new 关键字创建静态类类型的变量。 因为没有实例变量,所以要使用类名本身...

602
来自专栏Java技术栈

Java趣味分享:try/finally

考虑以下四个测试方法,它们会输出什么? public class Test { public static void main(String[] arg...

3194

扫描关注云+社区