标签:imp over 访问 stream ring cep 一起 通过 strong
原型模式(Prototype Pattern)属于对象创建型模式,通过克隆指定原型对象创建新对象。
优点:
缺点:
应用场景:
分类:
浅克隆
在浅克隆中,如果原型对象的成员变量是基本类型,String类型,包装类,则把成员变量复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
例:
原型类
1 /** 2 * 浅克隆 3 * 创建一个People类实现Cloneable接口 4 */ 5 public class People implements Cloneable{ 6 private int id; 7 private String name; 8 private Date currentDate = new Date(); //引用对象 9 10 public void setId(int id) { 11 this.id = id; 12 } 13 14 public int getId() { 15 return id; 16 } 17 18 public void setName(String name) { 19 this.name = name; 20 } 21 22 public String getName() { 23 return name; 24 } 25 26 public void setCurrentDate(Date currentDate) { 27 this.currentDate = currentDate; 28 } 29 30 public Date getCurrentDate() { 31 return currentDate; 32 } 33 34 //clone()方法其实是Object类中的方法。并且在Cloneable接口中都没有定义这个clone方法 35 @Override 36 protected People clone() throws CloneNotSupportedException { 37 People obj = (People) super.clone(); 38 return obj; 39 } 40 }
测试类
1 public class TestPeople { 2 public static void main(String[] args) throws CloneNotSupportedException { 3 People people = new People(); 4 people.setId(1); 5 people.setName("mali"); 6 people.setCurrentDate(new Date(1234567890L)); 7 System.out.println("****************初始化******************"); 8 System.out.println(people); 9 System.out.println(people.getId()+"\t"+people.getName()+"\t\t"+people.getCurrentDate()); 10 System.out.println("****************浅克隆******************"); 11 People clonePeople = people.clone(); 12 System.out.println(clonePeople); 13 System.out.println(clonePeople.getId()+"\t"+clonePeople.getName()+"\t\t"+clonePeople.getCurrentDate()); 14 System.out.println("克隆和被克隆中的日期对象地址是否相同:"+(people.getCurrentDate() == clonePeople.getCurrentDate())); 15 } 16 }
测试结果
****************初始化****************** testprototype.People@1540e19d 1 mali Thu Jan 15 14:56:07 CST 1970 ****************浅克隆****************** testprototype.People@135fbaa4 1 mali Thu Jan 15 14:56:07 CST 1970 克隆和被克隆中的日期对象地址是否相同:true //由此可以原型类中的引用成员变量和克隆类的相同成员变量所指地址相同
深克隆
在深克隆中,无论原型对象的成员变量是任何类型,都复制一份给克隆对象;也就是说原型对象中引用类型的成员变量和克隆对象中的相同成员变量所指地址不同。
例:
原型类
1 /** 2 * 深克隆 3 * 把原型类中的引用类型(String类,Integer包装类除外)也克隆 4 */ 5 public class Tree implements Cloneable{ 6 private int treeAge; 7 private String treeName; 8 private Date currentDate; 9 10 public void setTreeAge(int treeAge) { 11 this.treeAge = treeAge; 12 } 13 14 public int getTreeAge() { 15 return treeAge; 16 } 17 18 public void setTreeName(String treeName) { 19 this.treeName = treeName; 20 } 21 22 public String getTreeName() { 23 return treeName; 24 } 25 26 public void setCurrentDate(Date currentDate) { 27 this.currentDate = currentDate; 28 } 29 30 public Date getCurrentDate() { 31 return currentDate; 32 } 33 34 @Override 35 protected Tree clone() throws CloneNotSupportedException { 36 Object obj = super.clone(); 37 //深克隆操作 38 Tree tree = (Tree) obj; 39 tree.currentDate = (Date) this.currentDate.clone(); //克隆Date类 40 return tree; 41 } 42 }
测试类
1 public class TestTree { 2 public static void main(String[] args) throws CloneNotSupportedException { 3 Tree tree = new Tree(); 4 tree.setTreeAge(100); 5 tree.setTreeName("杨树"); 6 tree.setCurrentDate(new Date(1234567890123L)); 7 System.out.println("*******************初始化******************"); 8 System.out.println(tree.getTreeAge()+"\t\t"+tree.getTreeName()+"\t"+tree.getCurrentDate()); 9 System.out.println("*******************深克隆******************"); 10 Tree cloneTree = tree.clone(); 11 System.out.println(cloneTree.getTreeAge()+"\t\t"+cloneTree.getTreeName()+"\t"+cloneTree.getCurrentDate()); 12 System.out.println("克隆和被克隆的String地址是否相同: "+(tree.getTreeName() == cloneTree.getTreeName())); 13 System.out.println("克隆和被克隆中的日期对象地址是否相同:"+(tree.getCurrentDate() == cloneTree.getCurrentDate())); 14 System.out.println("*******************修改后******************"); 15 tree.setTreeAge(200); //原型类修改年龄 16 tree.setTreeName("柏树"); //原型类修改名称 17 tree.setCurrentDate(new Date(123456789012L)); //原型类修改当前时间 18 cloneTree.setCurrentDate(new Date()); //克隆类修改当前时间 19 System.out.println("Tree: "+tree.getTreeAge()+"\t\t"+tree.getTreeName()+"\t"+tree.getCurrentDate()); 20 System.out.println("cloneTree: "+cloneTree.getTreeAge()+"\t\t"+cloneTree.getTreeName()+"\t"+cloneTree.getCurrentDate()); 21 System.out.println("克隆和被克隆的String地址是否相同: "+(tree.getTreeName() == cloneTree.getTreeName())); 22 System.out.println("克隆和被克隆中的日期对象地址是否相同:"+(tree.getCurrentDate() == cloneTree.getCurrentDate())); 23 } 24 }
测试结果
*******************初始化****************** 100 杨树 Sat Feb 14 07:31:30 CST 2009 *******************深克隆****************** 100 杨树 Sat Feb 14 07:31:30 CST 2009 克隆和被克隆的String地址是否相同: true //由此可知原型类中的引用成员变量和克隆类的相同成员变量所指地址相同 克隆和被克隆中的日期对象地址是否相同:false //由此可知原型类中的引用成员变量和克隆类的相同成员变量所指地址不同 *******************修改后****************** Tree: 200 柏树 Fri Nov 30 05:33:09 CST 1973 cloneTree: 100 杨树 Tue Aug 06 11:50:18 CST 2019 克隆和被克隆的String地址是否相同: false 克隆和被克隆中的日期对象地址是否相同:false
序列化和反序列化克隆
把对象写到流中是序列化过程,从流中读取对象是反序列化过程。这种克隆方式也属于深克隆。需要克隆的类需要实现Cloneable接口和Serializable接口。
原型类
1 /** 2 * 序列化和反序列化进行深克隆 3 * 必须实现Serializable接口 4 */ 5 public class Car implements Cloneable, Serializable{ 6 private int price; 7 private String color; 8 private Date buyTime; 9 10 public int getPrice() { 11 return price; 12 } 13 14 public void setPrice(int price) { 15 this.price = price; 16 } 17 18 public String getColor() { 19 return color; 20 } 21 22 public void setColor(String color) { 23 this.color = color; 24 } 25 26 public Date getBuyTime() { 27 return buyTime; 28 } 29 30 public void setBuyTime(Date buyTime) { 31 this.buyTime = buyTime; 32 } 33 34 protected Object serClone() throws CloneNotSupportedException{ 35 ByteArrayOutputStream baos = null; 36 ObjectOutputStream oos = null; 37 ByteArrayInputStream bais = null; 38 ObjectInputStream ois = null; 39 Object obj = null; 40 try { 41 baos = new ByteArrayOutputStream(); 42 oos = new ObjectOutputStream(baos); 43 oos.writeObject(this); 44 bais = new ByteArrayInputStream(baos.toByteArray()); 45 ois = new ObjectInputStream(bais); 46 obj = ois.readObject(); 47 } catch (IOException e) { 48 e.printStackTrace(); 49 } catch (ClassNotFoundException e) { 50 e.printStackTrace(); 51 } 52 return obj; 53 } 54 }
测试类
1 public class TestCar { 2 public static void main(String[] args) throws CloneNotSupportedException { 3 Car car = new Car(); 4 car.setPrice(120000); 5 car.setColor("red"); 6 car.setBuyTime(new Date(1234567890123L)); 7 System.out.println("***************初始化**************"); 8 System.out.println(car.getPrice()+"\t"+car.getColor()+"\t\t"+car.getBuyTime()); 9 System.out.println("***************克隆后**************"); 10 Car cloneCar = (Car) car.serClone(); 11 System.out.println(cloneCar.getPrice()+"\t"+cloneCar.getColor()+"\t\t"+cloneCar.getBuyTime()); 12 System.out.println("克隆和被克隆中的日期对象地址是否相同:"+(car.getBuyTime() == cloneCar.getBuyTime())); 13 System.out.println("***************修改后**************"); 14 car.setPrice(200000); 15 car.setColor("blue"); 16 car.setBuyTime(new Date(12345678901234L)); 17 cloneCar.setBuyTime(new Date()); 18 System.out.println("car: "+car.getPrice()+"\t"+car.getColor()+"\t\t"+car.getBuyTime()); 19 System.out.println("cloneCar: "+cloneCar.getPrice()+"\t"+cloneCar.getColor()+"\t\t"+cloneCar.getBuyTime()); 20 System.out.println("克隆和被克隆中的日期对象地址是否相同:"+(car.getBuyTime() == cloneCar.getBuyTime())); 21 } 22 }
测试结果
***************初始化************** 120000 red Sat Feb 14 07:31:30 CST 2009 ***************克隆后************** 120000 red Sat Feb 14 07:31:30 CST 2009 克隆和被克隆中的日期对象地址是否相同:false ***************修改后************** car: 200000 blue Wed Mar 22 03:15:01 CST 2361 cloneCar: 120000 red Tue Aug 06 12:03:07 CST 2019 克隆和被克隆中的日期对象地址是否相同:false
结语:
在实际应用中,原型模式其实一般是和工厂方法一起使用,所以还是要码一下代码。而如果大家要是看懂了上面的代码,就可以轻松的码出需要的代码。
标签:imp over 访问 stream ring cep 一起 通过 strong
原文地址:https://www.cnblogs.com/mtgh/p/11308135.html