原型模式
2013-04-08 14:44
441 查看
一)故事
个性化电子账单
二)定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
三)代码例子
共计一个类:1)原型类;
1)原型类
一个类
场景使用例子
打印结果:
四)优点
1)性能优良
原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
2)逃避构造函数的约束
这即是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。
五)缺点
六)使用场景
1)资源优化场景
类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
2)性能和安全要求的场景
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
3)一个对象多个修改者的场景
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
原型模式已经与Java融为一体了,随时拿来用,java.lang.Cloneable
七)注意事项
1)构造函数不会被执行
2)浅拷贝和深拷贝
浅拷贝,即拷贝引用,指向原生对象的内部元素地址,共享一个私有变量。
深拷贝,即完全拷贝,两个对象这间没有任何的瓜葛,你修改你的,我修改我的,不相互影响。
注:深拷贝和浅拷贝建议不要混合使用,特别是在涉及类的继承时,父类有多个引用的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。
3)clone与final两个冤家
对象clone与对象内的final关键字是有冲突的,想要实现拷贝,则删除掉final关键字,这是最便捷、安全、快捷的方式。你要使用clone方法,在类的成员变量上就不要增加final关键字。
注:要使用clone方法,类的成员变量上就不要增加final关键字。
八)扩展
九)总结
理解浅拷贝和深拷贝,浅拷贝是引用,浅拷贝是完全拷贝。基本类型,如:int,long,double和String对象(String对象看作是基本类型)都是深拷贝,而数组(如:Integer[]、Double[])和对象(如:ArrayList<String>、Version())都是浅拷贝。想要实现数组和对象的深拷贝,则在clone()方法里加入深拷贝代码,如下:
// 实现java.lang.Cloneable接口中的方法clone()
public class PrototypeClass implements java.lang.Cloneable {
// 数组与对象
private ArrayList<String> list = new ArrayList(); // 引用拷贝(浅拷贝)
private Version version = new Version();// 引用拷贝(浅拷贝)
private Integer[] integerArray = new Integer[6];// 引用拷贝(浅拷贝)
private int arrayIndex = 0;
// 覆盖父类Object方法
@Override
protected PrototypeClass clone() {
PrototypeClass prototype = null;
try {
// 浅拷贝
prototype = (PrototypeClass)super.clone();
// 对象深拷贝
prototype.list = (ArrayList<String>)this.list.clone();
// 对象深拷贝
prototype.version = (Version)this.version.clone();
// 数组深拷贝
prototype.integerArray = (Integer[])this.integerArray.clone();
} catch (CloneNotSupportedException ex) {
}
return prototype;
}
}
个性化电子账单
二)定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
三)代码例子
共计一个类:1)原型类;
1)原型类
/** * 原型类 * * @author levovo */ public class PrototypeClass implements java.lang.Cloneable { private String title = null;// 完全拷贝(深拷贝) private String name = null;// 完全拷贝(深拷贝) private int number = 0; // 完全拷贝(深拷贝) // 数组与对象 private ArrayList<String> list = new ArrayList(); // 引用拷贝(浅拷贝) private Version version = new Version();// 引用拷贝(浅拷贝) private Integer[] integerArray = new Integer[6];// 引用拷贝(浅拷贝) private int arrayIndex = 0; // static private static Version versionStatic = new Version(); // 引用拷贝(浅拷贝)(仅有一个实例) private static int numberStatic = 0;// 引用拷贝(浅拷贝)(仅有一个实例) // final private final Version versionFinal = new Version(); private final int numberFinal = 999; // 覆盖父类Object方法 @Override protected PrototypeClass clone() { PrototypeClass prototype = null; try { // 浅拷贝 prototype = (PrototypeClass)super.clone(); // 对象深拷贝 prototype.list = (ArrayList<String>)this.list.clone(); // 对象深拷贝 prototype.version = (Version)this.version.clone(); // 数组深拷贝 prototype.integerArray = (Integer[])this.integerArray.clone(); } catch (CloneNotSupportedException ex) { } return prototype; } public void setTitle(String _title) { this.title = _title; // System.out.println("PrototypeClass()->setTitle():"+this.title); } public String getTitle() { return this.title; } /** * @return the number */ public int getNumber() { return number; } /** * @param number the number to set */ public void setNumber(int number) { this.number = number; } public void setList(String value) { this.getList().add(value); } public ArrayList<String> getList() { return this.list; } /** * @return the name */ public String getName() { 4000 return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @param list the list to set */ public void setList(ArrayList<String> list) { this.list = list; } /** * @return the version */ public Version getVersion() { return version; } /** * @param version the version to set */ public void setVersion(Version version) { this.version = version; } /** * @return the integerArray */ public Integer[] getIntegerArray() { return integerArray; } /** * @param integerArray the integerArray to set */ public void setIntegerArray(int integerArray) { this.integerArray[arrayIndex] = integerArray; } /** * @return the versionFinal */ public Version getVersionFinal() { return versionFinal; } /** * @return the numberFinal */ public int getNumberFinal() { return numberFinal; } /** * @return the versionStatic */ public static Version getVersionStatic() { return versionStatic; } /** * @param aVersionStatic the versionStatic to set */ public static void setVersionStatic(Version aVersionStatic) { versionStatic = aVersionStatic; } /** * @return the numberStatic */ public static int getNumberStatic() { return numberStatic; } /** * @param aNumberStatic the numberStatic to set */ public static void setNumberStatic(int aNumberStatic) { numberStatic = aNumberStatic; } }
一个类
/** * 一个类 * * @author levovo */ public class Version implements java.lang.Cloneable { private String name = null; private int code = 0; // 覆盖父类Object方法 @Override protected Version clone() { Version version = null; try { version = (Version)super.clone(); } catch (CloneNotSupportedException ex) { } return version; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the code */ public int getCode() { return code; } /** * @param code the code to set */ public void setCode(int code) { this.code = code; } }
场景使用例子
/** * 场景使用例子 * * @author levovo */ public class Client { public static void main(String[] args) { // 旧的 PrototypeClass prototypeOld = new PrototypeClass(); prototypeOld.setTitle("titleOld"); String name = new String("nameOld"); prototypeOld.setName(name); prototypeOld.setNumber(10001); prototypeOld.setList("listOld"); prototypeOld.getVersion().setName("version name....Old"); prototypeOld.getVersion().setCode(20001); prototypeOld.setIntegerArray(100); prototypeOld.setNumberStatic(100); prototypeOld.getVersionStatic().setName("version name...static...Old"); prototypeOld.getVersionStatic().setCode(30001); // prototypeOld.set // clone的 PrototypeClass prototypeClone = prototypeOld.clone(); // 修改 System.out.println("--- modify ---"); prototypeOld.setTitle("titleChange"); String name1 = new String("nameChange"); prototypeOld.setName(name1); prototypeOld.setNumber(10002); prototypeOld.setList("listChange"); prototypeOld.getVersion().setName("version name....Change"); prototypeOld.getVersion().setCode(20002); prototypeOld.setIntegerArray(200); prototypeOld.setNumberStatic(200); prototypeOld.getVersionStatic().setName("version name...static...Change"); prototypeOld.getVersionStatic().setCode(30002); System.out.println("--- 比较 ---"); // prototypeOld.getTitle().contains(name); if (prototypeOld.getTitle().equals(prototypeClone.getTitle())) { System.out.println("String title -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("String title -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getName().equals(prototypeClone.getName())) { System.out.println("String name -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("String name -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getNumber() == prototypeClone.getNumber()) { System.out.println("int number -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("int number -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getList().equals(prototypeClone.getList())) { System.out.println("ArrayList<String> list -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("ArrayList<String> list -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getVersion().equals(prototypeClone.getVersion())) { System.out.println("Version version -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("Version version -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getVersion().getName().equals(prototypeClone.getVersion().getName())) { System.out.println("Version version.getName() -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("Version version.getName() -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getVersion().getCode() == prototypeClone.getVersion().getCode()) { System.out.println("Version version.getCode() -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("Version version.getCode() -> 属于完全拷贝(深拷贝)"); } System.out.println("prototypeOld.getIntegerArray()[0]:"+prototypeOld.getIntegerArray()[0]); System.out.println("prototypeClone.getIntegerArray()[0]:"+prototypeClone.getIntegerArray()[0]); if (prototypeOld.getIntegerArray()[0] == prototypeClone.getIntegerArray()[0]) { System.out.println("Integer[] integerArray -> 属于引用拷贝(浅拷贝)"); }else{ System.out.println("Integer[] integerArray -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getNumberStatic() == prototypeClone.getNumberStatic()) { System.out.println("static int numberStatic -> 属于引用拷贝(浅拷贝)(仅一个实例)"); }else{ System.out.println("static int numberStatic -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getVersionStatic().equals(prototypeClone.getVersionStatic())) { System.out.println("static Version versionStatic -> 属于引用拷贝(浅拷贝)(仅一个实例)"); }else{ System.out.println("static Version versionStatic -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getVersionStatic().getName().equals(prototypeClone.getVersionStatic().getName())) { System.out.println("static Version versionStatic.getName() -> 属于引用拷贝(浅拷贝)(仅一个实例)"); }else{ System.out.println("static Version versionStatic.getName() -> 属于完全拷贝(深拷贝)"); } if (prototypeOld.getVersionStatic().getCode() == prototypeClone.getVersionStatic().getCode()) { System.out.println("static Version versionStatic.getCode() -> 属于引用拷贝(浅拷贝)(仅一个实例)"); }else{ System.out.println("static Version versionStatic.getCode() -> 属于完全拷贝(深拷贝)"); } System.out.println("prototypeOld.getNumberFinal():"+prototypeOld.getNumberFinal()); System.out.println("prototypeClone.getNumberFinal():"+prototypeClone.getNumberFinal()); // 总论: // 1)内部的数组(如Object[]和ArrayList<String>)和对象是拷贝引用,不是拷贝对象 // 2)基本类型是属于完全拷贝(深拷贝),String也算是基本类型 } }
打印结果:
--- modify --- --- 比较 --- String title -> 属于完全拷贝(深拷贝) String name -> 属于完全拷贝(深拷贝) int number -> 属于完全拷贝(深拷贝) ArrayList<String> list -> 属于完全拷贝(深拷贝) Version version -> 属于完全拷贝(深拷贝) Version version.getName() -> 属于完全拷贝(深拷贝) Version version.getCode() -> 属于完全拷贝(深拷贝) prototypeOld.getIntegerArray()[0]:200 prototypeClone.getIntegerArray()[0]:100 Integer[] integerArray -> 属于完全拷贝(深拷贝) static int numberStatic -> 属于引用拷贝(浅拷贝)(仅一个实例) static Version versionStatic -> 属于引用拷贝(浅拷贝)(仅一个实例) static Version versionStatic.getName() -> 属于引用拷贝(浅拷贝)(仅一个实例) static Version versionStatic.getCode() -> 属于引用拷贝(浅拷贝)(仅一个实例) prototypeOld.getNumberFinal():999 prototypeClone.getNumberFinal():999
四)优点
1)性能优良
原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
2)逃避构造函数的约束
这即是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。
五)缺点
六)使用场景
1)资源优化场景
类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
2)性能和安全要求的场景
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
3)一个对象多个修改者的场景
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
原型模式已经与Java融为一体了,随时拿来用,java.lang.Cloneable
七)注意事项
1)构造函数不会被执行
2)浅拷贝和深拷贝
浅拷贝,即拷贝引用,指向原生对象的内部元素地址,共享一个私有变量。
深拷贝,即完全拷贝,两个对象这间没有任何的瓜葛,你修改你的,我修改我的,不相互影响。
注:深拷贝和浅拷贝建议不要混合使用,特别是在涉及类的继承时,父类有多个引用的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。
3)clone与final两个冤家
对象clone与对象内的final关键字是有冲突的,想要实现拷贝,则删除掉final关键字,这是最便捷、安全、快捷的方式。你要使用clone方法,在类的成员变量上就不要增加final关键字。
注:要使用clone方法,类的成员变量上就不要增加final关键字。
八)扩展
九)总结
理解浅拷贝和深拷贝,浅拷贝是引用,浅拷贝是完全拷贝。基本类型,如:int,long,double和String对象(String对象看作是基本类型)都是深拷贝,而数组(如:Integer[]、Double[])和对象(如:ArrayList<String>、Version())都是浅拷贝。想要实现数组和对象的深拷贝,则在clone()方法里加入深拷贝代码,如下:
// 实现java.lang.Cloneable接口中的方法clone()
public class PrototypeClass implements java.lang.Cloneable {
// 数组与对象
private ArrayList<String> list = new ArrayList(); // 引用拷贝(浅拷贝)
private Version version = new Version();// 引用拷贝(浅拷贝)
private Integer[] integerArray = new Integer[6];// 引用拷贝(浅拷贝)
private int arrayIndex = 0;
// 覆盖父类Object方法
@Override
protected PrototypeClass clone() {
PrototypeClass prototype = null;
try {
// 浅拷贝
prototype = (PrototypeClass)super.clone();
// 对象深拷贝
prototype.list = (ArrayList<String>)this.list.clone();
// 对象深拷贝
prototype.version = (Version)this.version.clone();
// 数组深拷贝
prototype.integerArray = (Integer[])this.integerArray.clone();
} catch (CloneNotSupportedException ex) {
}
return prototype;
}
}
相关文章推荐
- 设计模式--原型模式
- 原型模式 - Prototype
- 《大话设计模式》java实现之原型模式
- JAVA设计模式之【原型模式】
- 面向对象的程序设计-原型模式
- 原型模式详解
- 设计模式之原型模式
- Java设计模式之Prototype原型模式
- 原型模式
- js原型模式
- 设计模式____原型设计模式(多实例模式)对应单列模式
- java原型模式
- 【设计模式】之原型模式
- (Prototype)原型模式的Java实现(转)
- Android设计模式系列(10)--SDK源码之原型模式
- Java设计模式之原型模式
- 原型模式
- 原型模式
- 设计模式之原型模式(Prototype)
- javascript 设计模式一:原型模式