设计模式——原型模式

原型模式的优点:简化对象的创建,使得创建对象就像复制粘贴一样easy。

使用原型模式创建对象,一般不会调用类的构造方法,Object的clone方法是一个本地方法,直接操作内存中的二进制流,在复制大对象时,性能差别非常明显。

 

关于深拷贝与浅拷贝

浅拷贝 - 拷贝的是值类型以及引用类型的地址

深拷贝 - 拷贝的是值类型,对于引用类型则是创建一个新的相同的对象,并使用新对象的地址;

将普通的引用类型的变量赋值给另一个变量,既不属于深拷贝,也不属于浅拷贝!

Object的clone方法是浅拷贝,值得一提的是,根据实际测试,对于String类型的拷贝,与值类型一样,实际上是拷贝的对象。其他引用类型则拷贝的是对象的地址!

下面看关于深拷贝与浅拷贝的代码 

/*
 * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved
 */

package com.pt.factory.method;

import com.pt.factory.abstracted.MountainBike;
import com.pt.factory.abstracted.RoadBikes;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @description
 * @author panteng
 * @date 17-2-3.
 */
public class GiantBike extends AbstractBike implements MountainBike, RoadBikes, Cloneable, Serializable {
    /** 自行车种类:山地车 or 公路车 */
    private String type = "";
    /** 自行车ID */
    private int id;
    /** 其他指标 */
    private Map<String, Object> map = new HashMap<String, Object>();

    /**
     * @description 展示外观
     * @param
     * @return
     * @throws
     */
    public void showAppearance(){
        System.out.println("我是捷安特自行车,Type=" + this.type);
    }

    /**
     * 使用Object默认的为浅拷贝
     * @return
     * @throws CloneNotSupportedException
     */
    public GiantBike clone() throws CloneNotSupportedException{
        return (GiantBike) super.clone();
    }

    /**
     * 深拷贝 - 采用串行化的方式
     * @return
     * @throws Exception
     */
    public GiantBike deepClone() throws Exception{
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(this);

        ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
        ObjectInputStream oi = new ObjectInputStream(bi);
        return (GiantBike) oi.readObject();
    }

    public String getType(){
        return type;
    }
    public void setType(String type){
        this.type = type;
    }
    public int getId(){
        return id;
    }
    public void setId(int id){
        this.id = id;
    }
    public Map<String, Object> getMap(){
        return map;
    }
    public void setMap(Map<String, Object> map){
        this.map = map;
    }
}
GiantBike
@Test
    public void testAssignment(){
        GiantBike bike1 = new GiantBike();
        bike1.setId(1);
        bike1.setType("giant1");

        GiantBike bike2 = new GiantBike();
        bike2.setType("giant2");
        bike2.setId(2);
        System.out.println(bike1 == bike2); //false

        //赋值既不属于深拷贝 也不属于浅拷贝
        bike2 = bike1;
        System.out.println(bike1 == bike2); //true

        bike2.setType("giant2");
        bike2.setId(2); //此处赋值会影响bike1的值
        System.out.println(bike1.getId());
    }

    @Test
    public void copyTest() throws Exception{
        GiantBike bike1 = new GiantBike();
        bike1.setId(1);
        bike1.setType("giant1");
        bike1.getMap().put("length", 90);

        //测试浅拷贝
        GiantBike bike2 = bike1.clone();
        System.out.println(bike2.getId() + " - " + bike2.getType() + " - " + bike2.getMap().get("length"));
        bike2.setId(2);
        bike2.setType("giant2");
        bike2.getMap().put("length", 92);//在此处获取的map 与 bike1的map是同一个map,说明是浅拷贝
        System.out.println(bike1.getId() + " - " + bike1.getType() + " - " + bike1.getMap().get("length"));

        //测试深拷贝
        GiantBike bike3 = bike1.deepClone();
        System.out.println(bike3.getId() + " - " + bike3.getType() + " - " + bike3.getMap().get("length"));
        bike3.setId(3);
        bike3.setType("giant3");
        bike3.getMap().put("length", 93);//在此处获取的map 与 bike1的map不是同一个map,说明是深拷贝
        System.out.println(bike1.getId() + " - " + bike1.getType() + " - " + bike1.getMap().get("length"));


    }
测试

 

原型模型比较简单,核心类是一个包含复制方法的类,需要实现cloneable接口,其他类继承此类,即可实现克隆!

/*
 * Copyright (c) 2017. Xiaomi.Co.Ltd All rights reserved
 */

package com.pt.prototype;

import java.io.*;

/**
 * @description
 * @author panteng
 * @date 17-2-6.
 */
public class PrototypeModle implements Cloneable, Serializable {
    /**
     * 使用Object默认的为浅拷贝
     * @return
     * @throws CloneNotSupportedException
     */
    public PrototypeModle clone() throws CloneNotSupportedException{
        return (PrototypeModle) super.clone();
    }

    /**
     * 深拷贝 - 采用串行化的方式
     * @return
     * @throws Exception
     */
    public PrototypeModle deepClone() throws Exception{
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(this);

        ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
        ObjectInputStream oi = new ObjectInputStream(bi);
        return (PrototypeModle) oi.readObject();
    }
}
PrototypeModle
@Test
    public void copyTest() throws Exception{
        Cells cell1 = new Cells();
        cell1.setId(1);
        cell1.setName("giant1");
        cell1.getMap().put("length", 90);

        //测试浅拷贝
        Cells cell2 = (Cells) cell1.clone();
        System.out.println(cell2.getId() + " - " + cell2.getName() + " - " + cell2.getMap().get("length"));
        cell2.setId(2);
        cell2.setName("giant2");
        cell2.getMap().put("length", 92);//在此处获取的map 与 cell1的map是同一个map,说明是浅拷贝
        System.out.println(cell1.getId() + " - " + cell1.getName() + " - " + cell1.getMap().get("length"));

        //测试深拷贝
        Cells cell3 = (Cells) cell1.deepClone();
        System.out.println(cell3.getId() + " - " + cell3.getName() + " - " + cell3.getMap().get("length"));
        cell3.setId(3);
        cell3.setName("giant3");
        cell3.getMap().put("length", 93);//在此处获取的map 与 cell1的map不是同一个map,说明是深拷贝
        System.out.println(cell1.getId() + " - " + cell1.getName() + " - " + cell1.getMap().get("length"));
        System.out.println(cell3.getId() + " - " + cell3.getName() + " - " + cell3.getMap().get("length"));
    }
测试

 

posted @ 2017-02-06 10:55  沙中世界  阅读(249)  评论(0编辑  收藏  举报