个人理解:
模式类型:
Prototype 原型模式 - 创建者模式
意图:
specifying the kind of objects to create using a prototypical instance
creating new objects by copying this prototype
概述:
原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.
原型模式中的拷贝分为"浅拷贝"和"深拷贝":
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.
注:使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
不是基本类型,所以成员变量不会被拷贝,需要我们自己实现深拷贝。
深拷贝与浅拷贝问题中,会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型。其余的都是浅拷贝。
Prototype - declares an interface for cloning itself.
ConcretePrototype - implements the operation for cloning itself.
模式的应用场景:
使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
结构图:

模式的优缺点:
使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
代码(其实读UML图要比代码还要一目了然):
2 、Rectangle.java
Square.java
3、 ShapeCache.java 【 Create a class to get concrete classes from database and store them in a Hashtable .】
4、 PrototypePatternDemo.java 【 PrototypePatternDemo uses ShapeCache class to get clones of shapes stored in a Hashtable .】
5、输出:
所有模式:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
补充模式:空对象模式
参考/转自:
http://blog.csdn.net/zhengzhb/article/details/7393528
http://www.tutorialspoint.com/design_pattern/prototype_pattern.htm
http://www.oodesign.com/prototype-pattern.html
http://blog.csdn.net/chjttony/article/details/7477346
模式类型:
Prototype 原型模式 - 创建者模式
意图:
specifying the kind of objects to create using a prototypical instance
creating new objects by copying this prototype
概述:
原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.
原型模式中的拷贝分为"浅拷贝"和"深拷贝":
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.
注:使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
不是基本类型,所以成员变量不会被拷贝,需要我们自己实现深拷贝。
深拷贝与浅拷贝问题中,会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型。其余的都是浅拷贝。
角色:
Client - creates a new object by asking a prototype to clone itself.Prototype - declares an interface for cloning itself.
ConcretePrototype - implements the operation for cloning itself.
模式的应用场景:
使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。
结构图:
模式的优缺点:
使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
代码(其实读UML图要比代码还要一目了然):
1、Shape.java
public abstract class Shape implements Cloneable {
private String id;
protected String type;
abstract void draw();
public String getType(){
return type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
2 、Rectangle.java
public class Rectangle extends Shape {
public Rectangle(){
type = "Rectangle";
}
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Square.java
public class Square extends Shape {
public Square(){
type = "Square";
}
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Circle.java
public class Circle extends Shape {
public Circle(){
type = "Circle";
}
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
3、 ShapeCache.java 【 Create a class to get concrete classes from database and store them in a Hashtable .】
import java.util.Hashtable;
public class ShapeCache {
private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();
public static Shape getShape(String shapeId) {
Shape cachedShape = shapeMap.get(shapeId);
//---这句是重点!!,返回的是对象的克隆!----
return (Shape) cachedShape.clone();
}
// for each shape run database query and create shape
// shapeMap.put(shapeKey, shape);
// for example, we are adding three shapes
public static void loadCache() {
Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(),circle);
Square square = new Square();
square.setId("2");
shapeMap.put(square.getId(),square);
Rectangle rectangle = new Rectangle();
rectangle.setId("3");
shapeMap.put(rectangle.getId(), rectangle);
}
}
4、 PrototypePatternDemo.java 【 PrototypePatternDemo uses ShapeCache class to get clones of shapes stored in a Hashtable .】
public class PrototypePatternDemo {
public static void main(String[] args) {
ShapeCache.loadCache();
Shape clonedShape = (Shape) ShapeCache.getShape("1");
System.out.println("Shape : " + clonedShape.getType());
Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
System.out.println("Shape : " + clonedShape2.getType());
Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
System.out.println("Shape : " + clonedShape3.getType());
}
}
5、输出:
Shape : Circle
Shape : Square
Shape : Rectangle
--===========================深拷备的分割线===============================--
深拷备是2种方法:
1、利用super.clone(); 后,再给不属于基本变量的类型属性赋值
package com.lee.desingerPattener23.prototype.example3;
class Professor implements Cloneable{
String name;
int age;
Professor(String name,int age){
this.name=name;
this.age=age;
}
public Object clone(){
Object o=null;
try{
o=super.clone();
}catch(CloneNotSupportedException e){
System.out.println(e.toString());
}
return o;
}
}
public class Student implements Cloneable{
String name;
int age;
Professor p;
Student(String name,int age,Professor p){
this.name=name;
this.age=age;
this.p=p;
}
public Object clone(){
Student o=null;
try{
o=(Student)super.clone();
}catch(CloneNotSupportedException e){
System.out.println(e.toString());
}
// --- 重点!:调用Professor类的clone()方法实现深拷贝 ---
o.p=(Professor)this.p.clone();
return o;
}
public static void main(String[] args){
Professor p=new Professor("wangwu",50);
Student s1=new Student("zhangsan",18,p);
Student s2=(Student)s1.clone();
s2.p.name="lisi";
s2.p.age=30;
//学生1的教授不改变
System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
System.out.println("name="+s2.p.name+","+"age="+s2.p.age);
}
}
2、利用序列化实现深度拷贝
把对象写到流里的过程是串行化(Serilization)过程,又叫对象序列化,而把对象从流中读出来的(Deserialization)过程叫反序列化。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来便可以重建对象。
package com.lee.desingerPattener23.prototype.example3;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
class Profess implements Serializable{
String name;
int age;
Profess(String name,int age){
this.name=name;
this.age=age;
}
}
public class StudentDeep implements Serializable{
String name;
int age;
Profess p;
StudentDeep(String name,int age,Profess p){
this.name=name;
this.age=age;
this.p=p;
}
public Object deepClone() throws IOException,OptionalDataException,ClassNotFoundException{
Object o = null;
try{
//将对象写到流里
ByteArrayOutputStream bo=new ByteArrayOutputStream();
ObjectOutputStream oo=new ObjectOutputStream(bo);
oo.writeObject(this);// object of studnet
oo.close();
//从流里读出来
ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=new ObjectInputStream(bi);
o = oi.readObject();
oi.close();
}catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e){
e.printStackTrace();
}
return o;
}
public static void main(String[] args) throws OptionalDataException, ClassNotFoundException, IOException{
Profess p=new Profess("wangwu",50);
StudentDeep s1=new StudentDeep("zhangsan",18,p);
StudentDeep s2=(StudentDeep)s1.deepClone();
s2.p.name="lisi";
s2.p.age=30;
//学生1的教授不改变
System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
System.out.println("name="+s2.p.name+","+"age="+s2.p.age);
}
}
输出结果:
name=wangwu,age=50
name=lisi,age=30
所有模式:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
补充模式:空对象模式
参考/转自:
http://blog.csdn.net/zhengzhb/article/details/7393528
http://www.tutorialspoint.com/design_pattern/prototype_pattern.htm
http://www.oodesign.com/prototype-pattern.html
http://blog.csdn.net/chjttony/article/details/7477346
转载请注明:http://blog.csdn.net/paincupid/article/details/46860283