23种设计模式之原型模式
上一节 23种设计模式之建造者模式
原型模式场景:
1、通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
2、就是Java种的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点。
3、优势有:效率高(直接克隆,避免了重新执行构造过程步骤)。
4、克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性值完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后,再修改克隆对象的值。
原型模式实现:
1、Cloneable接口和clone方法(clone不是Cloneable中的方法)
2、Prototype模式中实现起来最困难的地方就是内存复制操作,所幸再Java中提供了clone()方法替我们做了绝大部分事情。
Sheep类:
public class Sheep implements Cloneable,Serializable{
private String name;
private Date date;
/**
* 浅克隆
*/
// @Override
// protected Object clone() throws CloneNotSupportedException {
// Object obj=super.clone();
// return obj;
// }
/**
* 深克隆
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj=super.clone();
//深克隆
Sheep sheep=(Sheep) obj;
sheep.date=(Date) this.date.clone();
return obj;
}
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 Sheep(String name,Date date) {
this.name=name;
this.date=date;
}
public Sheep() {
}
}
原型模式可分为浅克隆和深克隆
浅克隆测试:
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException {
Date date=new Date(12312313123L);
Sheep s1=new Sheep("多莉", date);
Sheep s2=(Sheep) s1.clone();//此处克隆
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(s1.getDate());
//此时改变日期值,当浅克隆时,s2会改变;当深克隆时,s2不会改变
date.setTime(321321321321L);
System.out.println(s1.getDate());
System.out.println(s2);
System.out.println(s2.getName());
System.out.println(s2.getDate());
}
}
测试结果:
[email protected]
多莉
Sat May 23 20:05:13 CST 1970
Sat Mar 08 07:55:21 CST 1980
[email protected]
多莉
Sat Mar 08 07:55:21 CST 1980
深克隆测试:
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Date date=new Date(12312313123L);
Sheep s1=new Sheep("多莉", date);
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(s1.getDate());
//使用序列化和反序列化实现深克隆
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();//克隆好的对象
date.setTime(321321321321L);//此时改变日期值,s2不会改变
System.out.println(s1.getDate());
System.out.println(s2);
System.out.println(s2.getName());
System.out.println(s2.getDate());
}
}
测试结果:
[email protected]
多莉
Sat May 23 20:05:13 CST 1970
Sat Mar 08 07:55:21 CST 1980
[email protected]
多莉
Sat May 23 20:05:13 CST 1970
普通new方法和clone方法的比较
重写clone方法类:
class Laptop implements Cloneable{
public Laptop(){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj=super.clone();
return obj;
}
}
测试类:
public class Test3 {
public static void buildNew(int size){
long start=System.currentTimeMillis();
for(int i=0;i<size;i++){
Laptop laptop=new Laptop();
}
long end=System.currentTimeMillis();
System.out.println("new方法:"+(end-start));
}
public static void buildClone(int size) throws CloneNotSupportedException{
long start=System.currentTimeMillis();
Laptop laptop=new Laptop();
for(int i=0;i<size;i++){
Laptop laptop2=(Laptop) laptop.clone();
}
long end=System.currentTimeMillis();
System.out.println("clone方法:"+(end-start));
}
public static void main(String[] args) throws CloneNotSupportedException {
buildNew(1000);
buildClone(1000);
}
}
测试结果:
new方法:1699
clone方法:2
明显clone方法效率更高!
原型模式优点:
1、性能优良
原型模型是在内存二进制流的拷贝,要比直接new一个对象性能要好得多,特别是要在一个循环体内产生大量对象时,可以更好的体现。
2、逃避构造函数的约束
即使优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,减少了约束,在实际应用是需要考虑。
开发中的应用场景:
原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。
1、资源优化场景
类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等。
2、性能和安全要求的场景
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
3、一个对象多个修改者的场景
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
下一节 23种设计模式之适配器模式