Skip to content

原型模式

ZHI-XINHUA edited this page Jan 11, 2019 · 1 revision

原型模式

在JAVA语言中使用原型模式是非常简单的,这是因为Object类当中提供了一个本地方法clone,而JAVA中的任何类只要实现了Cloneable标识接口,就可以使用clone方法来进行对象的拷贝。

复制时构造方法是不被执行

浅度复制

被复制对象所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向 原来的对象。

直接使用object 的clone方法复制:

public Apple clone() {
        Apple apple = null;
        try {
            apple = (Apple)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return apple;

    }

深度复制

被复制对象的所有变量都包含与原来的对象相同的值,除去那些应用其他对象的变量。引用其他变量的对象将指向被复制过的新对象,而不再是原来的那些被引用的对象。换言之,深度复制就是复制的对象所引用的对象都复制咯一遍,而这种对被引用到的对象的复制叫做间接复制。

引用的对象也要自己实现复制

 public Apple depthClone(){
        Apple apple = null;
        try {
            apple = (Apple)super.clone();
            apple.producingPlace = producingPlace.clone();//复制引用对象

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return apple;
    }

完整栗子:

package com.prototype;

public class Apple implements Cloneable {
    private String varieties;
    private float weight;
    private String color;
    private ProducingPlace producingPlace;

    public Apple(String varieties,float weight,String color,ProducingPlace producingPlace){
        this.varieties = varieties;
        this.weight =weight;
        this.color = color;
        this.producingPlace = producingPlace;
        System.out.println("Apple constructor");
    }


    /**
     * 浅度复制:被复制对象所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向
     * 原来的对象。
     * @return
     */
    public Apple clone() {
        Apple apple = null;
        try {
            apple = (Apple)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return apple;

    }

    /**
     * 深度复制:被复制对象的所有变量都包含与原来的对象相同的值,除去那些应用其他对象的变量。
     * 引用其他变量的对象将指向被复制过的新对象,而不再是原来的那些被引用的对象。
     * 换言之,深度复制就是复制的对象所引用的对象都复制咯一遍,而这种对被引用到的对象的复制叫做间接复制
     * @return
     */
    public Apple depthClone(){
        Apple apple = null;
        try {
            apple = (Apple)super.clone();
            apple.producingPlace = producingPlace.clone();

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return apple;
    }

    @Override
    public String toString() {
        return "varieties:"+this.varieties+" weight:"+this.weight+" color:"+this.color+" producingPlace:"+producingPlace;
    }

    public float getWeight() {
        return weight;
    }

    public void setWeight(float weight) {
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getVarieties() {
        return varieties;
    }

    public void setVarieties(String varieties) {
        this.varieties = varieties;
    }

    public ProducingPlace getProducingPlace() {
        return producingPlace;
    }

    public void setProducingPlace(ProducingPlace producingPlace) {
        this.producingPlace = producingPlace;
    }
}

package com.prototype;

public class ProducingPlace implements Cloneable{
    private String province;
    private String city;

    public ProducingPlace(String province,String city){
        this.province = province;
        this.city =city;
        System.out.println("ProducingPlace constructor");
    }

    public ProducingPlace clone(){
        ProducingPlace p = null;
        try {
            p = (ProducingPlace)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }

    @Override
    public String toString() {
        return "ProducingPlace:"+super.toString();
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

测试:

package com.prototype;

public class PrototypeMain {
    public static void main(String[] args) {
        ProducingPlace p = new ProducingPlace("guangdong","guangzhou");
        Apple apple = new Apple("gz",2,"red",p);

        System.out.println("===clone====");
         System.out.println("original=="+apple.toString());
        Apple cloneApple = apple.clone();
        System.out.println("clone=="+cloneApple.toString());

        System.out.println("========depthClone========");
         System.out.println("original==" +apple.toString());
        Apple depthCloneApple = apple.depthClone();
        System.out.println("depthClone=="+depthCloneApple.toString());
    }
}

利用序列化和反序列化技术实现深克隆

//使用序列化和反序列化实现深复制
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(); //克隆好的对象!

结果:


ProducingPlace constructor
Apple constructor
===clone====
original==varieties:gz weight:2.0 color:red producingPlace:ProducingPlace:com.prototype.ProducingPlace@3796751b
clone==varieties:gz weight:2.0 color:red producingPlace:ProducingPlace:com.prototype.ProducingPlace@3796751b
========depthClone========
original==varieties:gz weight:2.0 color:red producingPlace:ProducingPlace:com.prototype.ProducingPlace@3796751b
depthClone==varieties:gz weight:2.0 color:red producingPlace:ProducingPlace:com.prototype.ProducingPlace@3796751b

开发中的应用场景

原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。

  • spring中bean的创建实际就是两种:单例模式和原型模式。(当然,原型模式需要和工厂模式搭配起来)