设计模式之原型模式
原型模式
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
即Java中的克隆技术,以某个对象为原型,复制出新对象,新对象具有原对象的特点;
优势:效率高
原型模式实现:
Cloneable接口和clone()方法
Sheep:
package com.prototype;
import java.io.Serializable;
import java.util.Date;
//多利羊
public class Sheep implements Cloneable,Serializable {
private String name;
private Date birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Sheep(String name, Date birthday) {
this.name = name;
this.birthday = birthday;
}
//重写clone()函数:浅克隆
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
}
Sheep2:
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();//直接调用object对象的clone()方法
//添加如下代码实现深复制
Sheep2 s = (Sheep2) obj;
s.birthday = (Date) this.birthday.clone();
return obj;
}
Client:
/**
* 测试浅克隆
*/
package com.prototype;
import java.util.Date;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date(1997);
Sheep s1 = new Sheep("多利",date);
Sheep s2 = (Sheep) s1.clone();//克隆s1
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(s1.getBirthday());
date.setTime(98868768);
System.out.println(s1.getBirthday());
System.out.println("----------------------");
System.out.println(s2);
s2.setName("少利");//修改名字
System.out.println(s2.getName());
System.out.println(s2.getBirthday());
}
}
结果:
com.prototype.Sheep@4554617c
多利
Thu Jan 01 08:00:01 CST 1970
Fri Jan 02 11:27:48 CST 1970
----------------------
com.prototype.Sheep@7f31245a
少利
Fri Jan 02 11:27:48 CST 1970
原型对象内容改变时,新对象也跟着改变
Client2
/**
* 测试深克隆
*/
package com.prototype;
import java.util.Date;
public class Client2 {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date(1997);
Sheep2 s1 = new Sheep2("多利",date);
Sheep2 s2 = (Sheep2) s1.clone();//克隆s1
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(s1.getBirthday());
date.setTime(98868768);
System.out.println(s1.getBirthday());
System.out.println("----------------------");
System.out.println(s2);
s2.setName("少利");//修改名字
System.out.println(s2.getName());
System.out.println(s2.getBirthday());
}
}
结果:
com.prototype.Sheep2@4554617c
多利
Thu Jan 01 08:00:01 CST 1970
Fri Jan 02 11:27:48 CST 1970
----------------------
com.prototype.Sheep2@7f31245a
少利
Thu Jan 01 08:00:01 CST 1970
原型对象内容改变时,新对象不改变
Client3:
/**
* 测试深克隆(通过序列化和反序列化实现深克隆)
*/
package com.prototype;
import java.io.*;
import java.util.Date;
public class Client3 {
public static void main(String[] args) throws Exception {
Date date = new Date(1997);
Sheep s1 = new Sheep("多利",date);
//Sheep2 s2 = (Sheep2) s1.clone();//克隆s1
//通过序列化和反序列化实现深克隆
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s1);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
Sheep s2 = (Sheep) ois.readObject();
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(s1.getBirthday());
date.setTime(98868768);
System.out.println(s1.getBirthday());
System.out.println("----------------------");
System.out.println(s2);
s2.setName("少利");//修改名字
System.out.println(s2.getName());
System.out.println(s2.getBirthday());
}
}
结果:
com.prototype.Sheep@135fbaa4
多利
Thu Jan 01 08:00:01 CST 1970
Fri Jan 02 11:27:48 CST 1970
----------------------
com.prototype.Sheep@3feba861
少利
Thu Jan 01 08:00:01 CST 1970
原型对象内容改变时,新对象不改变
Client4:
/**
* 短时间大量创建对象时,原型模式和普通new方式效率测试
*/
package com.prototype;
public class Client4 {
//使用new方法创建Laptop对象
public static void testNew(int size) {
long start = System.currentTimeMillis();//开始时间
Laptop laptop = new Laptop();
for(int i=0;i<size;i++) {
Laptop temp = new Laptop();
}
long end = System.currentTimeMillis();//结束时间
System.out.println("new耗时:"+(end-start));
}
//使用clone()创建Laptop对象
public static void testClone(int size) throws CloneNotSupportedException {
long start = System.currentTimeMillis();
Laptop laptop = new Laptop();
for(int i=0;i<size;i++) {
Laptop temp = (Laptop) laptop.clone();
}
long end = System.currentTimeMillis();
System.out.println("clone()耗时:"+(end-start));
}
public static void main(String[] args) throws CloneNotSupportedException {
testNew(100);
testClone(100);
}
}
//笔记本
class Laptop implements Cloneable {
//构造函数
public Laptop(){
try {
Thread.sleep(10);//模拟创建对象耗时过程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
}
结果:
new耗时:1100
clone()耗时:11
如果需要短时间创建大量对象,并且new的过程比较耗时,可以考虑使用原型模式