原型模式(prototype)
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
就是java的克隆技术,以某个对象为原型,复制出新的对象。显然新的对象具备原型对象的特点。
优势:效率高(直接克隆,避免了重新执行构造过程步聚)。
克隆类似于new,但是不同于new。New创建新的对象属性采用的默认值。克隆出的对象属性值的原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后在修改克隆对象的值。
原型模式的实现:
Cloneable接口和Clone方法。
Prototype模式中实现起来最困难的地方就是内存复制操作,所幸java中提供了clone()方法替我们做了绝大部他事情。
注意用词:克隆和拷贝是一回事。
浅克隆
publicclass User implements Cloneable {
private String name;
private Date birthday;
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
public Date getBirthday() {
returnbirthday;
}
publicvoid setBirthday(Date birthday) {
this.birthday = birthday;
}
public User() {
}
@Override
protected Object clone() {
Object obj;
try {
obj = super.clone();
return obj;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
returnnull;
}
}
publicclass Main {
publicstaticvoid main(String[] args) {
Date date = new Date(1234L);
User user1 = new User();
user1.setName("Lucy");
user1.setBirthday(date);
System.out.println(user1.getName());
System.out.println(user1.getBirthday());
//修改时间。
date.setTime(13145656789L);
user1.setBirthday(date);
System.out.println(user1.getBirthday());
//调用克隆方法复制类
User user2 = (User) user1.clone();
System.out.println(user2.getName());
System.out.println(user2.getBirthday());
}
}
输出结果:
Lucy
Thu Jan 01 08:00:01 CST 1970
Tue Jun 02 11:34:16 CST 1970
Lucy
Tue Jun 02 11:34:16 CST 1970
深克隆
publicclass User implements Cloneable {
private String name;
private Date birthday;
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
public Date getBirthday() {
returnbirthday;
}
publicvoid setBirthday(Date birthday) {
this.birthday = birthday;
}
public User() {
}
@Override
public Object clone() {
Object obj;
try {
obj = super.clone();
//添加如下代码,进行深克隆。
User user2 = (User) obj;
//克隆一个类的属性。
user2.birthday = (Date) this.birthday.clone();
return obj;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
returnnull;
}
}
publicclass Main {
publicstaticvoid main(String[] args) {
Date date = new Date(1234L);
User user1 = new User();
//调用克隆方法复制类
user1.setName("Lucy");
user1.setBirthday(date);
User user2 = (User) user1.clone();
System.out.println(user1.getName());
System.out.println(user1.getBirthday());
//修改时间。
date.setTime(13145656789L);
user1.setBirthday(date);
System.out.println("user1的生日:"+user1.getBirthday());
user2.setName("Rows");
System.out.println(user2.getName());
System.out.println("user2的生日:"+user2.getBirthday());
}
}
输出结果:
Lucy
Thu Jan 01 08:00:01 CST 1970
user1的生日:Tue Jun 02 11:34:16 CST 1970
Rows
user2的生日:Thu Jan 01 08:00:01 CST 1970
开发中的应用场景:
原型模式很少出现,一般是和工厂方法一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。
Spring中的bean的创建实际上就是两种:单例模式和原型模式。(当然,原型模式需要和工厂模式搭配起来)。
利用序列化和反序列化技术实现深克隆
publicstaticvoid main(String[] args) throws Exception {
Date date = new Date(1234L);
User user1 = new User();
// 调用克隆方法复制类
user1.setName("Lucy");
user1.setBirthday(date);
User user2 = (User) user1.clone();
// 通过序列化和反序列化深复制对象
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(user1);
byte[] by = bos.toByteArray();
//反序列化
ByteArrayInputStream bin = new ByteArrayInputStream(by);
ObjectInputStream ois = new ObjectInputStream(bin);
User user3 = (User) ois.readObject();
System.out.println(user1.getName());
System.out.println(user1.getBirthday());
// 修改时间。
date.setTime(13145656789L);
user1.setBirthday(date);
System.out.println("user1的生日:" + user1.getBirthday());
user2.setName("Rows");
System.out.println(user2.getName());
System.out.println("user2的生日:" + user2.getBirthday());
System.out.println(user3.getName());
System.out.println("user3的生日:" + user3.getBirthday());
}
输出内容:
Lucy
Thu Jan 01 08:00:01 CST 1970
user1的生日:Tue Jun 02 11:34:16 CST 1970
Rows
user2的生日:Thu Jan 01 08:00:01 CST 1970
Lucy
user3的生日:Thu Jan 01 08:00:01 CST 1970
