设计模式-原型模式(Prototype)

  • Specify the kinds of objects to create using a prototypical instance,and create new objects bycopying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)简单说明就是不通过new关键字产生对象,而是通过对象复制来实现就叫做原型模式。

原型模式的核心就是一个clone()方法,通过该方法进行对象拷贝,java底层提供了一个Cloneable接口来标示这个对象是可拷贝的,这个借口只是一个标记作用,在JVM中有这个标记的对象才能被拷贝。

原型模式注意事项

1.构造函数不会被执行。我们举例说明为什么不会执行构造函数。

/**
 * @author shuliangzhao
 * @Title: Car
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/5/31 22:57
 */
public class Car implements Cloneable{

    public Car() {
        System.out.println("我是一辆跑车...");
    }

    @Override
    public Car clone() {
        Car car = null;
        try{
            car = (Car)super.clone();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return car;
    }
}

客户端

/**
 * @author shuliangzhao
 * @Title: CarClient
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/5/31 22:59
 */
public class CarClient {

    public static void main(String[] args) {
        Car car = new Car();
        Car clone = car.clone();
    }
}

运行结果



从运行结果我们可以看出只打印一句话 说明构造函数没执行。Object类的clone方法的原理是从内存中(具体地说就是堆内存)以二进制流的方式进行拷贝,重新分配一个内存块,那构造函数没有被执行也是非常正常的了。

浅拷贝和深拷贝

浅拷贝例子
/**
 * 浅拷贝
 * @author shuliangzhao
 * @Title: Thing
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/5/31 22:26
 */
public class ShallowThing implements Cloneable {

    private List list = new ArrayList();

    @Override
    public ShallowThing clone() {
        ShallowThing thing = null;
        try {
            thing = (ShallowThing) super.clone();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return thing;
    }

    public void setList(String s) {
        this.list.add(s);
    }

    public List getList() {
        return this.list;
    }


}

客户端Client

/**
 * @author shuliangzhao
 * @Title: Client
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/5/31 22:30
 */
public class Client {

    public static void main(String[] args) {
        //浅拷贝
        ShallowThing thing = new ShallowThing();
        thing.setList("张三");
        ShallowThing clone = thing.clone();
        clone.setList("李四");
        System.out.println(thing.getList());
        //深拷贝
       /* DeepThing deepThing = new DeepThing();
        deepThing.setList("王五");
        DeepThing clone1 = deepThing.clone();
        clone1.setList("张柳");
        System.out.println(deepThing.getList());
        System.out.println(clone1.getList());*/
    }
}

执行结果


image.png

执行结果是两个,因为java做了一个偷懒的动作,clone方法只拷贝对象,对象内的数组和引用对象等都不拷贝,这就是浅拷贝。两个对象共享一个变量是一种非常不安全的方式。但是String字符串比较特殊,通过字符串池(stringpool)在需要的时候才在内存中创建新的字符串。所以使用String时候可以当做基本类型就可以。

深拷贝例子

/**
 * @author shuliangzhao
 * @Title: DeepThing
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/5/31 22:32
 */
public class DeepThing implements Cloneable{

    private ArrayList list = new ArrayList();

    @Override
    public DeepThing clone() {
        DeepThing thing = null;
        try {
            thing = (DeepThing) super.clone();
            this.list = (ArrayList)this.list.clone();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return thing;
    }

    public void setList(String s) {
        this.list.add(s);
    }

    public List getList() {
        return this.list;
    }

}

客户端Client

/**
 * @author shuliangzhao
 * @Title: Client
 * @ProjectName design-parent
 * @Description: TODO
 * @date 2019/5/31 22:30
 */
public class Client {

    public static void main(String[] args) {
        //浅拷贝
        /*ShallowThing thing = new ShallowThing();
        thing.setList("张三");
        ShallowThing clone = thing.clone();
        clone.setList("李四");
        System.out.println(thing.getList());*/
        //深拷贝
        DeepThing deepThing = new DeepThing();
        deepThing.setList("王五");
        DeepThing clone1 = deepThing.clone();
        clone1.setList("张柳");
        System.out.println(deepThing.getList());
        System.out.println(clone1.getList());
    }
}

执行结果


image.png

从上图可以看出第一个执行结果只有一个值。这就是深拷贝。

原型模式优点

1.性能好,因为是二进制拷贝,比new一个对象性能好。
2.不依赖构造函数

你可能感兴趣的:(设计模式-原型模式(Prototype))