设计模式——原型模式
Posted 知止
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式——原型模式相关的知识,希望对你有一定的参考价值。
1.描述
用原型实例制定创建对象的种类,并且通过复制这些原型创建的对象。
2.模式的使用
·抽象原型(Prototype):一个接口。负责定义对象复制自身的方法。
·具体原型(ConcretePrototype):实现Prototype接口的类。具体原型实现抽象原型中的方法,以便所创建的对象调用该方法复制自己。
3.使用情景
·程序需要从一个对象出发,得到若干和其状态相同,并可独立变化其状态的对象时。
·当对象的创建需要独立于他的构建和表示时。
·一个类创建实例状态不是很多,那么就可以将这个类的一个实例定义为原型,那么可以通过复制该原型得到新的实例,这可能比重新使用该类的构造方法创建实例方便。
4.优点
·复制已有实例可以提高效率时。
·可以动态保存当前对象状态。在运行时,可以随时使用对象流保存当前对象的一个复制。
·可以在运行时创建新的对象,无需创建一系列类和继承结构。
·可以动态添加、删除原型的复制品
5.UML图
6案例
clone()方法
java.lang包中的Object类提供了一个权限是protected的用于复制对象的clone()方法。java中所有的类都继承了该方法,但由于该方法是protected的,如果一个对象想使用该方法得到自己的一个复制,就必须保证自己与所在的类在同一个包中,这显然是不可能的,因为java不允许用户将包名命名为java.lang。
为了能让一个对象使用clone()方法,创建该对象的类可以重写clone方法(super即可),并将权限设为public。
另外,当对象调用Object中的clone()方法时,JVM会逐个复制对象的成员变量,然后创建一个新的对象返回,所以JVM要求调用clone()方法的对象必须实现Cloneable接口。Cloneable接口中没有任何方法,其唯一的作用就是让JVM知道实现该接口的对象可以被复制。
1 package 原型模式; 2 3 public class test1 { 4 5 public static void main(String[] args) { 6 Circle circle = new Circle(); 7 circle.setRadius(11.22); 8 try { 9 Circle circleCopy = (Circle) circle.clone(); 10 System.out.println("circlr中的数据:" + circle.getRadius()); 11 System.out.println("circlrCopy中的数据:" + circleCopy.getRadius()); 12 } catch (CloneNotSupportedException e) { 13 // TODO Auto-generated catch block 14 e.printStackTrace(); 15 } 16 } 17 18 } 19 20 class Circle implements Cloneable{ 21 private double radius; 22 23 public double getRadius() { 24 return radius; 25 } 26 27 public void setRadius(double radius) { 28 this.radius = radius; 29 } 30 31 public Object clone() throws CloneNotSupportedException{ 32 Object object = super.clone(); 33 return object; 34 } 35 }
深度克隆
Object中的clone()方法将复制对象中的值来创建新对象,如果当前对象拥有的成员变量是一个对象,那么clone()方法将会复制当前对象的引用,并没有复制该对象的所拥有的变量。所以在进行克隆时,必须对对象所包含的其他对象进行复制。
1 package 原型模式; 2 3 public class test2 { 4 5 public static void main(String[] args) { 6 A a = new A(1.1); 7 B b = new B(a, 2); 8 try { 9 B bCopy = (B) b.clone(); 10 System.out.println("a中的属性:" + a.a); 11 System.out.println("b中的属性 int b:" + b.b); 12 System.out.println("b中的属性 A a:" + b.a.getClass()); 13 System.out.println("bCopy中的属性 int b:" + bCopy.b); 14 System.out.println("bCopy中的属性 A a:" + bCopy.a.getClass()); 15 //分别改变对象的属性 16 b.a.a = 2.2; 17 System.out.println("b中的属性 A a的属性:" + b.a.a); 18 bCopy.a.a = 3.3; 19 System.out.println("bCopy中的属性 A a的属性:" + bCopy.a.a); 20 } catch (CloneNotSupportedException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } 24 } 25 26 } 27 28 class A implements Cloneable{ 29 double a; 30 A(double a){ 31 this.a = a; 32 } 33 34 public Object clone() throws CloneNotSupportedException{ 35 Object o = super.clone(); 36 return o; 37 } 38 } 39 40 class B implements Cloneable{ 41 int b; 42 A a;//a对象必须重写了clone()方法 43 B(A a, int b){ 44 this.a = a; 45 this.b = b; 46 } 47 48 public Object clone() throws CloneNotSupportedException{ 49 B b = (B)super.clone(); 50 b.a = (A)a.clone(); 51 return b; 52 53 } 54 }
Serializable接口与克隆对象
相对于clone()方法,java提供了一种简单的复制方案,使用Serializable接口和对象流来进行复制。
这种方法需要保证被复制的对象即其成员变量中的对象都必须实现了Serializable接口。
1 package 原型模式; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.IOException; 6 import java.io.ObjectInputStream; 7 import java.io.ObjectOutputStream; 8 import java.io.Serializable; 9 10 public class test3 { 11 12 public static void main(String[] args) { 13 Goat goat = new Goat(); 14 goat.setColor("白色"); 15 Goat goatCopy = (Goat)goat.clone(); 16 System.out.println(goatCopy.hashCode());//完全复制后 17 System.out.println(goatCopy.getColor()); 18 goatCopy.setColor("黑色"); 19 System.out.println(goat.hashCode()); 20 System.out.println(goatCopy.hashCode()); 21 } 22 23 } 24 25 class Goat implements Serializable{ 26 String color; 27 28 public String getColor() { 29 return color; 30 } 31 32 public void setColor(String color) { 33 this.color = color; 34 } 35 36 public Object clone() { 37 Object o = null; 38 ByteArrayOutputStream out1 = new ByteArrayOutputStream(); 39 try { 40 ObjectOutputStream out2 = new ObjectOutputStream(out1); 41 out2.writeObject(this);//将对象写入输出流 42 ByteArrayInputStream in1 = new ByteArrayInputStream(out1.toByteArray()); 43 ObjectInputStream in2 = new ObjectInputStream(in1); 44 o = in2.readObject(); 45 } catch (IOException e) { 46 // TODO Auto-generated catch block 47 e.printStackTrace(); 48 } catch (ClassNotFoundException e) { 49 // TODO Auto-generated catch block 50 e.printStackTrace(); 51 } 52 53 return o; 54 } 55 }
以上是关于设计模式——原型模式的主要内容,如果未能解决你的问题,请参考以下文章