设计模式之原型模式

1、核心本质:

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

2、应用场景:

-通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

3、原型模式实现:

-Cloneable接口和clone方法(不属于Cloneable接口,是Object类中的方法,通过override该方法实现拷贝)
-Prototype模式中实现起来最困难的地方就是内存复制操作,所幸在java中提供了clone()方法替我们做了绝大部分事情

4、浅复制与深复制的概念

浅复制:复制对象与原对象所有成员变量的值相等,包括引用成员变量(即复制对象与原对象引用成员变量都指向同一个对象)。
深复制:复制对象与原对象所有成员变量(除引用变量外)都相等,虽然引用变量的值不同,但引用变量指向的对象成员数据相等。
深复制与浅复制

代码示例:

/**
 * 实体类(实现浅复制)
 * @author ly1
 *
 */
public class Car1 implements Cloneable,Serializable{
    private String name;
    private Date cloneDate;
    public Car1(String name, Date cloneDate) {
        super();
        this.name = name;
        this.cloneDate = cloneDate;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getCloneDate() {
        return cloneDate;
    }
    public void setCloneDate(Date cloneDate) {
        this.cloneDate = cloneDate;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }


}
/**
 * 原型模式(浅复制)
 * @author ly1
 *
 */
public class Client1 {
    public static void main(String[] args) throws Exception {
        Date date = new Date(1231312312312L);
        Car1 c1 = new Car1("奥迪",date);
        Car1 c2 = (Car1) c1.clone();

        System.out.println("修改前:");
        System.out.println("c1-->date:"+c1.getCloneDate());
        System.out.println("c2-->date:"+c2.getCloneDate());

        date.setTime(917239817932172L);
        System.out.println("修改后:");
        System.out.println("c1-->date:"+c1.getCloneDate());
        System.out.println("c2-->date:"+c2.getCloneDate());
    }
}

结果:
修改前:
c1-->date:Wed Jan 07 15:11:52 CST 2009
c2-->date:Wed Jan 07 15:11:52 CST 2009
修改后:
c1-->date:Fri Mar 04 22:18:52 CST 31036
c2-->date:Fri Mar 04 22:18:52 CST 31036
import java.util.Date;

/**
 * 实体类(实现深复制)
 * @author ly1
 *
 */
public class Car2 implements Cloneable{
    private String name;
    private Date cloneDate;
    public Car2(String name, Date cloneDate) {
        super();
        this.name = name;
        this.cloneDate = cloneDate;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getCloneDate() {
        return cloneDate;
    }
    public void setCloneDate(Date cloneDate) {
        this.cloneDate = cloneDate;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //将对象的成员变量(除基本类型和String类型)也都克隆一份,实现深复制
        Object clone = super.clone();
        Car2 car = (Car2) clone;
        car.cloneDate = (Date) this.cloneDate.clone();
        return car;
    }
}
import java.util.Date;

/**
 * 原型模式(浅复制)
 * @author ly1
 *
 */
public class Client2 {
    public static void main(String[] args) throws Exception {
        Date date = new Date(1231312312312L);
        Car2 c1 = new Car2(new String("奥迪"),date);
        Car2 c2 = (Car2) c1.clone();

        System.out.println("修改前:");
        System.out.println("c1-->date:"+c1.getCloneDate());
        System.out.println("c2-->date:"+c2.getCloneDate());

        date.setTime(917239817932172L);
        System.out.println("修改后:");
        System.out.println("c1-->date:"+c1.getCloneDate());
        //由于实现了深复制,改变对象c1的成员变量,c2的成员变量不改变
        System.out.println("c2-->date:"+c2.getCloneDate());
    }
}

结果:
修改前:
c1-->date:Wed Jan 07 15:11:52 CST 2009
c2-->date:Wed Jan 07 15:11:52 CST 2009
修改后:
c1-->date:Fri Mar 04 22:18:52 CST 31036
c2-->date:Wed Jan 07 15:11:52 CST 2009
5、使用序列化与反序列化实现深复制
/**
 * 使用序列化和反序列化技术实现深复制
 *      要求实体类实现java.io.Serializable接口
 * @author ly1
 *
 */
public class Client3 {
    public static void main(String[] args) throws Exception {
        Date date  = new Date(12312312L);
        Car1 car = new Car1("宝马",date);

        //使用序列化和反序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(car);
        byte[] bytes = bos.toByteArray();
        oos.flush();
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        Car1 car2 = (Car1) ois.readObject();
        ois.close();

        System.out.println(car);
        System.out.println(car2);

        System.out.println("原型:-->date" + car.getCloneDate());
        System.out.println("克隆:-->date" + car2.getCloneDate());

        System.out.println("修改前:");
        System.out.println("c1-->date:"+car.getCloneDate());
        System.out.println("c2-->date:"+car2.getCloneDate());

        date.setTime(917239817932172L);
        System.out.println("修改后:");
        System.out.println("c1-->date:"+car.getCloneDate());
        System.out.println("c2-->date:"+car2.getCloneDate());

    }
}

结果:
Prototype.Car1@8ea9cf1
Prototype.Car1@729f624a
原型:-->dateThu Jan 01 11:25:12 CST 1970
克隆:-->dateThu Jan 01 11:25:12 CST 1970
修改前:
c1-->date:Thu Jan 01 11:25:12 CST 1970
c2-->date:Thu Jan 01 11:25:12 CST 1970
修改后:
c1-->date:Fri Mar 04 22:18:52 CST 31036
c2-->date:Thu Jan 01 11:25:12 CST 1970
6、new方式与clone方式效率对比
/**
 * 测试new方式和clone()方式(原型模式)的效率
 * @author ly1
 *
 */
public class Client4 {
    public static void testNew(){
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            Rocket r = new Rocket();
        }
        long end = System.currentTimeMillis();
        System.out.println("new方式耗时:"+(end - start)+"ms");
    }
    public static void testClone() throws Exception{
        Rocket r = new Rocket();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            Rocket r1 = (Rocket) r.clone();
        }
        long end = System.currentTimeMillis();
        System.out.println("clone方式耗时:"+(end - start)+"ms");
    }

    public static void main(String[] args) throws Exception {
        testNew();
        testClone();
    }
}


class Rocket implements Cloneable{
    public Rocket(){
        try {
            Thread.sleep(10);           //线程休眠10ms,模拟创建对象耗时现象
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

结果:
new方式耗时:10093ms
clone方式耗时:0ms

分析:

-很显然clone方式快得多,直接从内存复制。
-如果创建对象很耗时,可以采用原型模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值