原型模式:
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
深克隆和浅克隆:
1、对于浅克隆
public class People implements Cloneable {
String name;
int age;
Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public People(String name, int age, Date date) {
super();
this.name = name;
this.age = age;
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "People [name=" + name + ", age=" + age + ", date=" + date + "]";
}
public People() {
super();
}
public People(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试类:
public class Client {
public static void main(String[] args) throws Exception {
Date date = new Date(2364262352L);
System.out.println(date);
People p1 = new People("张三", 18,date);
date.setTime(62786892498243L);
System.out.println(date);
People p2 = (People) p1.clone();
System.out.println(p1);
System.out.println(p2);
System.out.println(p1.hashCode() +"-----"+p2.hashCode());
/*
* 打印结果:
*
* People [name=张三, age=18, date=Sat Aug 22 11:28:18 GMT+08:00 3959]
* People [name=张三, age=18, date=Sat Aug 22 11:28:18 GMT+08:00 3959]
*发现:克隆之后在修改时间依然还是没有变化。
* */
}
}
对于浅克隆,如图所示:
深克隆:
这里有两种方式:
1、通过重写clone方法,来实现深克隆。
/**
* 深度克隆
* */
public class People2 implements Cloneable {
String name;
int age;
Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public People2(String name, int age, Date date) {
super();
this.name = name;
this.age = age;
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "People [name=" + name + ", age=" + age + ", date=" + date + "]";
}
public People2() {
super();
}
public People2(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
protected People2 clone() throws CloneNotSupportedException {
//在克隆对象的同时把对象的属性也给克隆了
Object obj = super.clone();
People2 p = (People2) obj;
Date d = (Date) p.date.clone();
p.setDate(d);
return p;
}
}
测试代码:
public class Client2 {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date(2678264781672L);
People2 p = new People2("张三",12,date);
People2 p1 = p.clone();
date.setTime(897892798732L);
System.out.println(p);
System.out.println(p1);
/*
* 打印结果:
* People [name=张三, age=12, date=Mon Jun 15 14:39:58 GMT+08:00 1998]
* People [name=张三, age=12, date=Sat Nov 14 18:26:21 GMT+08:00 2054]
* 可以观察到深度克隆之后,在修改属性此时就会发生变化
* */
}
}
第二种方式,通过序列化和反序列化来实现:
public class People3 implements Serializable {
private static final long serialVersionUID = 1L;
String name;
Date date;
@Override
public String toString() {
return "People3 [name=" + name + ", date=" + date + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public People3(String name, Date date) {
super();
this.name = name;
this.date = date;
}
public People3() {
super();
// TODO Auto-generated constructor stub
}
//内容写到数组里边然后在读取 , 通过此种方式来深度复制对象
public People3 clone(People3 p){
//定义这个数组用于接收对象信息
byte[] by=null;
//初始化字节数组输出流
ByteArrayOutputStream baos = null;
//初始化对象输出流
ObjectOutputStream oos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
//将对象写入到硬盘中
oos.writeObject(p);
by = baos.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if (oos != null) {
oos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//获取字节数组输入流
ByteArrayInputStream bais = null;
//获得对象输入六
ObjectInputStream ois = null;
try {
//读取by数组
bais = new ByteArrayInputStream(by);
ois = new ObjectInputStream(bais);
//通过反序列化读取到对象
People3 p1= (People3) ois.readObject();
//System.out.println(p);
return p1;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
bais.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
if (ois != null) {
ois.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
测试代码:
public class Client3 {
public static void main(String[] args) {
Date d = new Date(35483782375L);
System.out.println(d);
People3 p = new People3("张三",d);
People3 p1 = p.clone(p);
d.setTime(78946582782L);
System.out.println("p的时间"+"---"+d);
System.out.println("p"+"---"+p);
System.out.println("p1"+"---"+p1);
/*
* 打印结果:
* Tue Feb 16 00:36:22 GMT+08:00 1971
* p的时间---Mon Jul 03 01:36:22 GMT+08:00 1972
* p---People3 [name=张三, date=Mon Jul 03 01:36:22 GMT+08:00 1972]
* p1---People3 [name=张三, date=Tue Feb 16 00:36:22 GMT+08:00 1971]
*
* 如上一种深克隆一样
* */
}
}
那么,原型模式到底在什么时候用?
假设一个系统的产品类是动态加载的,而且产品类具有一定的等级结构。这个时候如果采取工厂模式的话,工厂类就不得不具有一个相应的等级结构。而产品品类的等级结构一旦变化,工厂类的等级结构就不得不有以恶相应的变化。这对于产品结构可能会有经常变化的系统来说,采用工厂模式就有不方便之处。
此时若采用原型模式,给每一个产品类配备一个克隆方法(大多时候只需个产品类等级结构配备一个根类配备一个克隆方法),便可免去工厂模式所带来的据哟有固定等级结构的工厂类。
还有一点,假设通过普通方法创建对象很耗时时,也可采用原型模式,例如:
/**
* 测试普通new方式创建对象和clone方式创建对象的效率差异!
* 如果需要短时间创建大量对象,并且new的过程比较耗时。则可以考虑使用原型模式!
*
*
*/
public class Client4 {
public static void testNew(int size){
long start = System.currentTimeMillis();
for(int i=0;i<size;i++){
Laptop t = new Laptop();
}
long end = System.currentTimeMillis();
System.out.println("new的方式创建耗时:"+(end-start));
}
public static void testClone(int size) throws CloneNotSupportedException{
long start = System.currentTimeMillis();
Laptop t = new Laptop();
for(int i=0;i<size;i++){
Laptop temp = (Laptop) t.clone();
}
long end = System.currentTimeMillis();
System.out.println("clone的方式创建耗时:"+(end-start));
}
public static void main(String[] args) throws Exception {
testNew(1000);
testClone(1000);
/**
* 测试结果:
* new的方式创建耗时:10288
* clone的方式创建耗时:10
*
*
* */
}
}
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(); //直接调用object对象的clone()方法!
return obj;
}
}
本文详细介绍了原型模式的概念及应用场景,通过对比浅克隆和深克隆的区别,展示了如何实现深克隆的不同方法,并探讨了在何种情况下选择原型模式进行对象创建更为高效。
306

被折叠的 条评论
为什么被折叠?



