创建型设计模式-prototype
原型设计模式已经继承到java中,即通过clone方法复制一个对象。类图如下:
ProtoType模式需要满足以下两个条件
1 .实现Cloneable接口,只有实现Cloneable接口,在运行期才可以安全的复制对象,否则会报CloneNotSupportedException异常
2.重写Object类中的clone方法。Object为所有类的父类,因为Object中的Clone访问使用Protected修饰,故需要子类重写Clone方法,使用public修饰。
使用clone方法复制对象和使用构造new对象有什么区别吗?为什么设计模式建议使用clone,而不是重新new 对象呢?
1. 当调用对象的clone方法时,首先会分配一个和原对象大小相同的空间,使用原对象中对应的各个域,填充新对象的域,然后返回。它直接操作内存中的二进制流,在复制大对象时,性能差别很明显。2.如果创建类通过new的过程很复杂,使用prototype可以省去大量创建代码。
深拷贝 and 浅拷贝
浅拷贝只会拷贝结基本的数据类型,对于数组、容器对象引用对象等都不会拷贝,如果需求中可能有会设置改变原类型中数组或容器或引用对象操作则会出现以下问题。
** * Created by fengxinzi on 18-1-17. */ public class Glass implements Cloneable { String color ; String heigh ; public Water getWater() { return water; } public void setWater(Water water) { this.water = water; } private Water water ; public Glass(String color , String heigh , Water water){ this.color = color; this.heigh = heigh; this.water = water; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getHeigh() { return heigh; } public void setHeigh(String heigh) { this.heigh = heigh; } public Glass Clone() throws CloneNotSupportedException{ return (Glass)super.clone(); } }
/** * Created by fengxinzi on 18-1-17. */ public class Water { String colorName ; public Water(String colorName){ this.colorName = colorName; } public void setColorName (String colorName){ this.colorName = colorName; } public String getColorName(){ return colorName; } }
public class CloneTest { @Test public void testClone(){ Water water = new Water("可乐"); Glass glass = new Glass("透明","10cm",water); Glass cloneGlass = null; try { cloneGlass = glass.Clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } if(cloneGlass != null){ //克隆的基本数据类型完全隔离,不会影响原型。 cloneGlass.setColor("不透明"); System.out.println(cloneGlass.getColor()); System.out.println(glass.getColor()); //克隆的引用类型默认不隔离,影响原型 // Water water1 = new Water("咖啡"); cloneGlass.getWater().setColorName("咖啡"); System.out.println(cloneGlass.getWater().getColorName()); System.out.println(glass.getWater().getColorName()); } } }
输出如下
不透明
透明
咖啡
咖啡
cloneGlass = glass.Clone(); cloneGlass.water =cloneGlass.water.Clone();
4 原型模式直接通过二进制流赋值对象,所以不care 访问修饰符。而单例模式中通过修改构造的修饰符来达到单例。故两个设计模式是冲突的,使用时候应该注意。