第0章:简介
原型模式定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
原型模式的实质:克隆生成对象
参考:http://chjavach.iteye.com/blog/1623968,研磨设计模式(书籍),大话设计模式(书籍)
模式图:
待补充
第1章:实践
第0节:自定义原型模式
(1)原型接口(Prototype.java)
package com.mcc.core.designPattern.build.prototype.customPrototype; /** * 原型接口 * * @author <a href="mailto:417877417@qq.com">menergy</a> * DateTime: 14-3-9 下午4:59 */ public interface Prototype { /** * 克隆自身的方法 * @return */ public Prototype clone(); } |
(2)产品类(Product.java)
package com.mcc.core.designPattern.build.prototype.customPrototype; /** * 产品类(自定义) * * @author <a href="mailto:417877417@qq.com">menergy</a> * DateTime: 14-3-9 下午5:04 */ public class Product implements Prototype { private String property1; private String property2; public String getProperty1() { return property1; } public void setProperty1(String property1) { this.property1 = property1; } public String getProperty2() { return property2; } public void setProperty2(String property2) { this.property2 = property2; } @Override public String toString() { return "Product{" + "property1='" + property1 + '\'' + ", property2='" + property2 + '\'' + '}'; } /** * 克隆自身,属性是值类型,属于浅度克隆 * @return */ @Override public Prototype clone() { Product product = new Product(); product.setProperty1(this.property1); product.setProperty2(this.property2); return product; } } |
(3)目标克隆对象类(PrototypeImpl.java)
package com.mcc.core.designPattern.build.prototype.customPrototype; /** * 目标克隆对象(自定义) * * 原型模式的定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 * 原型模式的本质:克隆生成对象 * * @author <a href="mailto:417877417@qq.com">menergy</a> * DateTime: 14-3-9 下午5:06 */ public class PrototypeImpl implements Prototype { //值类型属性 private String property3; private String property4; //引用类型属性 private Product product; public String getProperty3() { return property3; } public void setProperty3(String property3) { this.property3 = property3; } public String getProperty4() { return property4; } public void setProperty4(String property4) { this.property4 = property4; } public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } @Override public String toString() { return "PrototypeImpl{" + "property1='" + product.getProperty1() + '\'' + "property2='" + product.getProperty2() + '\'' + "property3='" + property3 + '\'' + ", property4='" + property4 + '\'' + '}'; } /** * 对象克隆自身,含引用类型属性,采用深度克隆方式 * @return */ @Override public Prototype clone() { PrototypeImpl prototypeImpl = new PrototypeImpl(); prototypeImpl.setProperty3(this.property3); prototypeImpl.setProperty4(this.property4); //引用类型属性克隆 prototypeImpl.setProduct((Product)this.product.clone()); return prototypeImpl; } } |
(4)客户端测试类(Client.java)
package com.mcc.core.designPattern.build.prototype.customPrototype; /** * 客户端测试 * * @author <a href="mailto:417877417@qq.com">menergy</a> * DateTime: 14-3-9 下午5:20 */ public class Client { public static void main(String args[]){ //第一个实例 PrototypeImpl prototypeImpl1 = new PrototypeImpl(); Product product = new Product(); product.setProperty1("value1"); product.setProperty2("value2"); prototypeImpl1.setProduct(product); prototypeImpl1.setProperty3("value3"); prototypeImpl1.setProperty4("value4"); System.out.println("第一个实例:" + prototypeImpl1); //第二个实例,通过克隆获取 PrototypeImpl prototypeImpl2 = (PrototypeImpl)prototypeImpl1.clone(); //修改值 prototypeImpl2.getProduct().setProperty1("值1"); prototypeImpl2.setProperty3("值3"); System.out.println("第二个实例(克隆):" + prototypeImpl2); System.out.println("再看第一个实例(原实例):" + prototypeImpl1); } } |
第1节:java自带原型模式
(1)产品类(Product.java)
package com.mcc.core.designPattern.build.prototype.javaPrototype; /** * 产品对象(Java自实现) * * @author <a href="mailto:417877417@qq.com">menergy</a> * DateTime: 14-3-9 下午5:04 */ public class Product implements Cloneable { private String property1; private String property2; public String getProperty1() { return property1; } public void setProperty1(String property1) { this.property1 = property1; } public String getProperty2() { return property2; } public void setProperty2(String property2) { this.property2 = property2; } @Override public String toString() { return "Product{" + "property1='" + property1 + '\'' + ", property2='" + property2 + '\'' + '}'; } /** * 克隆自身,属性是值类型,属于浅度克隆 * @return */ public Object clone() { Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; } } |
(2)目标克隆对象类(PrototypeImpl.java)
package com.mcc.core.designPattern.build.prototype.javaPrototype; /** * 目标克隆对象(Java自实现) * * 原型模式的定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 * 原型模式的本质:克隆生成对象 * * @author <a href="mailto:417877417@qq.com">menergy</a> * DateTime: 14-3-9 下午5:06 */ public class PrototypeImpl implements Cloneable { //值类型属性 private String property3; private String property4; //引用类型属性 private Product product; public String getProperty3() { return property3; } public void setProperty3(String property3) { this.property3 = property3; } public String getProperty4() { return property4; } public void setProperty4(String property4) { this.property4 = property4; } public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } @Override public String toString() { return "PrototypeImpl{" + "property1='" + product.getProperty1() + '\'' + "property2='" + product.getProperty2() + '\'' + "property3='" + property3 + '\'' + ", property4='" + property4 + '\'' + '}'; } /** * 对象克隆自身,含引用类型属性,采用深度克隆方式 * @return */ public Object clone() { PrototypeImpl obj = null; try { obj = (PrototypeImpl)super.clone(); //这个很重要,引用类型自身克隆 obj.setProduct((Product)this.product.clone()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return obj; } } |
(3)客户端测试(Client.java)
package com.mcc.core.designPattern.build.prototype.javaPrototype; /** * 客户端测试 * * @author <a href="mailto:417877417@qq.com">menergy</a> * DateTime: 14-3-9 下午5:51 */ public class Client { public static void main(String args[]){ //第一个实例 PrototypeImpl prototypeImpl1 = new PrototypeImpl(); Product product = new Product(); product.setProperty1("value1"); product.setProperty2("value2"); prototypeImpl1.setProduct(product); prototypeImpl1.setProperty3("value3"); prototypeImpl1.setProperty4("value4"); System.out.println("第一个实例:" + prototypeImpl1); //第二个实例,通过克隆获取 PrototypeImpl prototypeImpl2 = (PrototypeImpl)prototypeImpl1.clone(); //修改值 prototypeImpl2.getProduct().setProperty1("值1"); prototypeImpl2.setProperty3("值3"); System.out.println("第二个实例(克隆):" + prototypeImpl2); System.out.println("再看第一个实例(原实例):" + prototypeImpl1); } } |
思考:
Java自带的原型模式,要求实现Cloneable接口,实现机制是在运行时通知虚拟机可以安全的使用Clone方法,如果没有实现这个接口却去调用,则会抛出CloneNotSupportedException异常。java中所有的类都是Object类的子类,Object类中有一个clone方法,该方法的作用域时protected类型,一般的类时无法调用的。Prototype类会将clone方法的作用域修改为public类型。而且,对象的复制是通过调用Object类的clone方法,不会调用类的构造方法,它直接在内存中复制数据。因此,不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。
原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。原型模式很少单独出现。经常与其他模式混用。
需要注意, 单例模式将构造方法的访问权限设置为private型。但clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。