原型模式:
原型模式是一种创建型模式,通过复制已存在的实例来获得新的实例,而不是新建实例。被复制的实例就是所称的原型,这个原型是可定制的,短时间创建大量对象时,可以考虑使用原型模式
Tip:原型模式中的拷贝分为浅拷贝和深拷贝:
浅拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。
深拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。
类图:
应用场景:
原型模式很少单独出现,一般利用工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。
spring中bean的创建实际就两种:单例模式和原型模式。
应用实例:
Demo1:浅拷贝
1 package prototype.domain; 2 3 import java.io.Serializable; 4 import java.util.Date; 5 6 public class Student implements Cloneable,Serializable{ 7 /** 8 * 9 */ 10 private static final long serialVersionUID = 1L; 11 private String sname; 12 private int age; 13 private Date birthday; 14 15 public Student () 16 { 17 18 } 19 20 public Student(String sname, int age, Date birthday) 21 { 22 super(); 23 this.sname = sname; 24 this.age = age; 25 this.birthday = birthday; 26 } 27 28 @Override 29 public Object clone() throws CloneNotSupportedException 30 { 31 Object obj = super.clone(); 32 33 return obj; 34 } 35 36 public String getSname() { 37 return sname; 38 } 39 public void setSname(String sname) { 40 this.sname = sname; 41 } 42 public int getAge() { 43 return age; 44 } 45 public void setAge(int age) { 46 this.age = age; 47 } 48 public Date getBirthday() { 49 return birthday; 50 } 51 public void setBirthday(Date birthday) { 52 this.birthday = birthday; 53 } 54 55 @Override 56 public String toString() { 57 return "Student [sname=" + sname + ", age=" + age + ", birthday=" 58 + birthday + "]"; 59 } 60 61 @Override 62 public int hashCode() { 63 final int prime = 31; 64 int result = 1; 65 result = prime * result + age; 66 result = prime * result 67 + ((birthday == null) ? 0 : birthday.hashCode()); 68 result = prime * result + ((sname == null) ? 0 : sname.hashCode()); 69 return result; 70 } 71 72 @Override 73 public boolean equals(Object obj) { 74 if (this == obj) 75 return true; 76 if (obj == null) 77 return false; 78 if (getClass() != obj.getClass()) 79 return false; 80 Student other = (Student) obj; 81 if (age != other.age) 82 return false; 83 if (birthday == null) { 84 if (other.birthday != null) 85 return false; 86 } else if (!birthday.equals(other.birthday)) 87 return false; 88 if (sname == null) { 89 if (other.sname != null) 90 return false; 91 } else if (!sname.equals(other.sname)) 92 return false; 93 return true; 94 } 95 96 97 98 }
深拷贝Demo2:
1 package prototype.domain; 2 3 import java.io.Serializable; 4 import java.util.Date; 5 6 public class Student implements Cloneable,Serializable{ 7 /** 8 * 9 */ 10 private static final long serialVersionUID = 1L; 11 private String sname; 12 private int age; 13 private Date birthday; 14 15 public Student () 16 { 17 18 } 19 20 public Student(String sname, int age, Date birthday) 21 { 22 super(); 23 this.sname = sname; 24 this.age = age; 25 this.birthday = birthday; 26 } 27 28 @Override 29 public Object clone() throws CloneNotSupportedException 30 { 31 Object obj = super.clone(); 32 33 //实现深复制功能(deep Clone) 34 Student s = (Student)obj; 35 //把属性也进行克隆! 36 s.birthday = (Date)this.birthday.clone(); 37 38 return obj; 39 } 40 41 public String getSname() { 42 return sname; 43 } 44 public void setSname(String sname) { 45 this.sname = sname; 46 } 47 public int getAge() { 48 return age; 49 } 50 public void setAge(int age) { 51 this.age = age; 52 } 53 public Date getBirthday() { 54 return birthday; 55 } 56 public void setBirthday(Date birthday) { 57 this.birthday = birthday; 58 } 59 60 @Override 61 public String toString() { 62 return "Student [sname=" + sname + ", age=" + age + ", birthday=" 63 + birthday + "]"; 64 } 65 66 @Override 67 public int hashCode() { 68 final int prime = 31; 69 int result = 1; 70 result = prime * result + age; 71 result = prime * result 72 + ((birthday == null) ? 0 : birthday.hashCode()); 73 result = prime * result + ((sname == null) ? 0 : sname.hashCode()); 74 return result; 75 } 76 77 @Override 78 public boolean equals(Object obj) { 79 if (this == obj) 80 return true; 81 if (obj == null) 82 return false; 83 if (getClass() != obj.getClass()) 84 return false; 85 Student other = (Student) obj; 86 if (age != other.age) 87 return false; 88 if (birthday == null) { 89 if (other.birthday != null) 90 return false; 91 } else if (!birthday.equals(other.birthday)) 92 return false; 93 if (sname == null) { 94 if (other.sname != null) 95 return false; 96 } else if (!sname.equals(other.sname)) 97 return false; 98 return true; 99 } 100 101 102 103 }
1 package prototype.service; 2 3 import java.util.Date; 4 5 import prototype.domain.Student; 6 7 public class DeepClientTest { 8 9 public static void main(String[] args) throws CloneNotSupportedException { 10 // TODO Auto-generated method stub 11 Date date = new Date(12312321331L); 12 Student s1 = new Student("少利",12, date); 13 Student s2 = (Student)s1.clone(); //实现深复制。s2对象的birthday是一个新对象! 14 15 16 System.out.println(s1); 17 System.out.println(s1.getSname()); 18 System.out.println(s1.getBirthday()); 19 20 date.setTime(23432432423L); 21 22 System.out.println(s1.getBirthday()); 23 24 25 s2.setSname("多利"); 26 System.out.println(s2); 27 System.out.println(s2.getSname()); 28 System.out.println(s2.getBirthday()); 29 } 30 31 }
Demo3:通过序列化实现深拷贝
1 package prototype.service; 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.util.Date; 9 10 import prototype.domain.Student; 11 12 public class ClientSerialTet { 13 14 public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException { 15 // TODO Auto-generated method stub 16 // TODO Auto-generated method stub 17 Date date = new Date(12312321331L); 18 Student s1 = new Student("少利",12, date); 19 //Student s2 = (Student)s1.clone(); //实现深复制。s2对象的birthday是一个新对象! 20 // 使用序列化和反序列化实现深复制 21 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 22 ObjectOutputStream oos = new ObjectOutputStream(bos); 23 oos.writeObject(s1); 24 byte[] bytes = bos.toByteArray(); 25 26 ByteArrayInputStream bis = new ByteArrayInputStream(bytes); 27 ObjectInputStream ois = new ObjectInputStream(bis); 28 29 Student s2 = (Student) ois.readObject(); //克隆好的对象! 30 31 System.out.println(s1); 32 System.out.println(s1.getSname()); 33 System.out.println(s1.getBirthday()); 34 35 date.setTime(23432432423L); 36 37 System.out.println(s1.getBirthday()); 38 39 40 s2.setSname("多利"); 41 System.out.println(s2); 42 System.out.println(s2.getSname()); 43 System.out.println(s2.getBirthday()); 44 } 45 46 }