设计模式5——原型模式(创建型模式)

原型模式,根据现有的实例变量( A ),复制(克隆)出相同类型的实例变量 ( B )。

要理解原型模式的实质,核心的要点是搞清楚 “ 深复制 ” 和 “ 浅复制 ”。

一,“ 深复制 ” 和 “ 浅复制 ” 的概念和区别

浅复制:使用一个已知实例 ( A ) 对新创建实例 ( B ) 的成员变量逐个赋值,这个方式也被称为浅拷贝

深复制:不仅要复制对象的所有非引用类型成员(即基本数据类型变量,如int、boolean、char等)变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。

通过以上概念可以得知:

浅复制时,实例变量中的引用变量的值(该值是地址,不是变量的实际内容)也是相同的,即指向(堆中)同一个对象。

深复制需要做的是:在堆中新建引用类型的成员实例对象,并将该新建的成员实例对象的地址赋值给新实例变量 ( B ) 的成员(引用类型,值是地址)。

二, 原型模式的实现:实现Cloneable接口(Java)

原型模式本质上是要实现复制(克隆)。

复制又分为 “ 深复制 ” 和 “ 浅复制 ”。Java 中通过让一个类实现 cloneable 接口,并重写 clone() 函数,在 clone() 函数中,执行旧对象向新对象进行成员变量赋值操作,实现一个对象的复制(克隆)。

简单的“成员变量的逐一拷贝赋值”实现的是浅复制。

要保证“深复制”的实现,需要该对象引用的其他对象(即对象中的非基本类型成员变量)也要实现 Cloneable 接口并重写 clone()方法。

按照上面的结论,实现以下代码 Body 类组合了 Head 类,要想深拷贝 Body 类,必须在 Body 类的 clone 方法中将 Head 类也要拷贝一份。代码如下:

1.static class Body implements Cloneable{
2. public Head head;
3. public Body() {}
4. public Body(Head head) {this.head = head;}
5. @Override
6. protected Object clone() throws CloneNotSupportedException {
7. Body newBody = (Body) super.clone();
8. newBody.head = (Head) head.clone();
9. return newBody;
10. }
11.}

12.static class Head implements Cloneable{
13. public Face face;
14. public Head() {}
15. @Override
16. protected Object clone() throws CloneNotSupportedException {
17. return super.clone();
18. } }

19.public static void main(String[] args) throws CloneNotSupportedException {
20. Body body = new Body(new Head(new Face()));
21. Body body1 = (Body) body.clone();
22. System.out.println("body == body1 : " + (body == body1) );
23. System.out.println("body.head == body1.head : " + (body.head == body1.head));
24.}

打印结果为:

1. body == body1 : false
2. body.head == body1.head : false

注意:以上示例代码中,Head 在 clone 时不保证是 “ 深复制 ”,因为 Head 中的 Face 也是个引用变量,是否是 “ 深复制 ” 取决于:原 Head 对象新 “ 克隆 ” 出的新 Head 对象中的 Face 是如何赋值的。

三,原型模式的结构图

原型模式框架图

我个人理解,所谓的原型模式就是要实现一个可以自我克隆的接口,实际编码时需要重点考虑的是克隆如何实现,以及克隆的效果如何,是 “深克隆” 还是 “浅克隆”。

猜你喜欢

转载自blog.csdn.net/ding3106/article/details/81951590