java设计模式之原型模式

来源:互联网 发布:手机角度水平仪软件 编辑:程序博客网 时间:2024/06/06 02:46

   原型模式是一种比较简单的设计模式,也非常的容易理解,属于创建型设计模式的一种,只实现一个接口,重写一个方法即可完成原型模式。那么我们就来看看吧。

一、定义

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。


二、适用情况

创建一些大对象,比较耗时的对象的时候,可以使用原型模式提高创建对象的效率。


三、原型模式实现

1、实现Cloneable接口,在java中有一个Cloneable接口,它的作用只有一个,就是通知虚拟机可以安全的在实现了此接口的类上使用clone()方法。如果你想看下这个接口,其实可以告诉你,并没有什么可看的,只是一个标识接口,实现此接口就是表示了这个类具有被Clone的能力,如果没有实现此接口,而去使用clone(),就会抛出CloneNotSupportedException异常。

2、重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。

下面就以羊来为原型克隆多利

代码实现

package cn.wong.pattern.prototype;import java.util.Date;public class Sheep implements Cloneable {    private String name;    private Date birthDay;    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    public Sheep() {    }    public Sheep(String name, Date birthDay) {        this.name = name;        this.birthDay = 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;    }}
package cn.wong.pattern.prototype;import java.util.Date;public class Client {    public static void main(String[] args) throws CloneNotSupportedException {        Sheep s1 = new Sheep("芬兰母羊",new Date(324324234L));        System.out.println(s1);        System.out.println(s1.getName());        System.out.println(s1.getBirthDay());        System.out.println("---------进行clone----------");        Sheep s2 = (Sheep)s1.clone();        System.out.println(s2);        System.out.println(s2.getName());        System.out.println(s2.getBirthDay());    }}

结果:

cn.wong.pattern.prototype.Sheep@4633c1aa芬兰母羊Mon Jan 05 02:05:24 CST 1970---------进行clone----------cn.wong.pattern.prototype.Sheep@28a50395芬兰母羊Mon Jan 05 02:05:24 CST 1970

从结果可以看出拷贝出来的是一个新的对象,并和原始对象具有相同的属性值

使用原型模式创建对象比直接new一个对象在性能上要好很多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
protected native Object clone() throws CloneNotSupportedException;

使用原型模式的注意事项

1. 使用原型模式不会调用类的构造方法,因为它是直接在内存中进行复制的。
2. 深拷贝和浅拷贝


四、浅拷贝和深拷贝

Object类的clone方法只会拷贝对象中的8中基本数据类型,对于数组、日期、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝

浅拷贝:

package cn.wong.pattern.prototype;import java.util.Date;public class Sheep implements Cloneable {    private String name;    private Date birthDay;    @Override    public Object clone() throws CloneNotSupportedException {        Object obj = super.clone();        /*Sheep s = (Sheep)obj;        s.birthDay=(Date) this.birthDay.clone();*/        return obj;    }    public Sheep() {    }    public Sheep(String name, Date birthDay) {        this.name = name;        this.birthDay = 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;    }}
package cn.wong.pattern.prototype;import java.util.Date;public class Client {    public static void main(String[] args) throws CloneNotSupportedException {        Date date = new Date(324324234L);        Sheep s1 = new Sheep("芬兰母羊",date);        System.out.println("---------打印s1的信息----------");        System.out.println(s1);        System.out.println(s1.getName());        System.out.println(s1.getBirthDay());        //进行复制        Sheep s2 = (Sheep)s1.clone();        //修改s1所指向的时间        date.setTime(23432454354L);        System.out.println("\n---------再次打印s1的信息----------");        System.out.println(s1.getName());        System.out.println(s1.getBirthDay());        System.out.println("\n---------打印s2的信息----------");        System.out.println(s2);        System.out.println(s2.getName());        System.out.println(s2.getBirthDay());    }}

结果:

---------打印s1的信息----------cn.wong.pattern.prototype.Sheep@5df1cc1a芬兰母羊Mon Jan 05 02:05:24 CST 1970---------再次打印s1的信息----------芬兰母羊Tue Sep 29 13:00:54 CST 1970---------打印s2的信息----------cn.wong.pattern.prototype.Sheep@7a0ec850芬兰母羊Tue Sep 29 13:00:54 CST 1970

发现s2的信息是改变时间后的,我们知道,clone是在修改时间前进行。所以由此我们可以知道引用类型对象不会进行拷贝,s1、s2两个对象同时都是指向同一个Date,这就是浅拷贝。

深拷贝:

如果要实现深拷贝,必须将引用对象另行拷贝。而对于java的大部分的类都实现了Cloneable接口,所以深拷贝并不困难。

修改Sheep中clone方法

@Override    public Object clone() throws CloneNotSupportedException {        Object obj = super.clone();        Sheep s = (Sheep)obj;        s.birthDay=(Date) this.birthDay.clone();        return obj;    }

测试不变

package cn.wong.pattern.prototype;import java.util.Date;public class Client {    public static void main(String[] args) throws CloneNotSupportedException {        Date date = new Date(324324234L);        Sheep s1 = new Sheep("芬兰母羊",date);        System.out.println("---------打印s1的信息----------");        System.out.println(s1);        System.out.println(s1.getName());        System.out.println(s1.getBirthDay());        //进行复制        Sheep s2 = (Sheep)s1.clone();        //修改s1所指向的时间        date.setTime(23432454354L);        System.out.println("\n---------再次打印s1的信息----------");        System.out.println(s1.getName());        System.out.println(s1.getBirthDay());        System.out.println("\n---------打印s2的信息----------");        System.out.println(s2);        System.out.println(s2.getName());        System.out.println(s2.getBirthDay());    }}

结果

---------打印s1的信息----------cn.wong.pattern.prototype.Sheep@2d8eef25芬兰母羊Mon Jan 05 02:05:24 CST 1970---------再次打印s1的信息----------芬兰母羊Tue Sep 29 13:00:54 CST 1970---------打印s2的信息----------cn.wong.pattern.prototype.Sheep@60813aca芬兰母羊Mon Jan 05 02:05:24 CST 1970
0 0
原创粉丝点击