文档章节

原型模式

清尘V
 清尘V
发布于 2016/04/18 09:26
字数 1394
阅读 14
收藏 0
  • 先定义基本对象:

package com.whereta.prototype;

import java.io.Serializable;

/**
 * Vincent 创建于 2016/4/18.
 */
public class Company implements Cloneable,Serializable{
    /**
     * 公司名字
     */
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.whereta.prototype;

/**
 * Vincent 创建于 2016/4/18.
 * 用户对象
 */
public class User implements  Cloneable {
    /**
     * 用户年龄
     */
    private  int age;
    /**
     * 用户姓名
     */
    private String name;
    /**
     * 公司
     */
    private Company company;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
package com.whereta.prototype;

import java.io.*;

/**
 * Vincent 创建于 2016/4/18.
 * 深度复制用户对象
 */
public class DeepUser implements Cloneable,Serializable{
    /**
     * 用户年龄
     */
    private int age;
    /**
     * 用户姓名
     */
    private String name;
    /**
     * 公司
     */
    private Company company;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        try {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();

            ObjectOutputStream oo = new ObjectOutputStream(bo);

            oo.writeObject(this);        //read from stream
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());

            ObjectInputStream oi = new ObjectInputStream(bi);

            return (oi.readObject());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}


  • 使用原型模式之前先看下我们平时经常用的引用复制指向:

package com.whereta.prototype;

import com.alibaba.fastjson.JSON;

/**
 * Vincent 创建于 2016/4/18.
 * 此处是简单复制,即不同对象指向同一个引用地址
 */
public class SimpleCopyObject {

    public static void main(String[] args) {
        User user = new User();
        User user1 = user;

        System.out.println(user);
        System.out.println(user1);

        user.setAge(23);

        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(user1));


        user.setAge(24);

        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(user1));
    }


}
  • 输出结果:

Connected to the target VM, address: '127.0.0.1:55324', transport: 'socket'
com.whereta.prototype.User@6ba8fb1b
com.whereta.prototype.User@6ba8fb1b
{"age":23}
{"age":23}
{"age":24}
{"age":24}
Disconnected from the target VM, address: '127.0.0.1:55324', transport: 'socket'
  • 从输出结果可以看出:两个对象实际指向的是同一个地址,所以修改任何一个对象都可以引起另一个对象的改变

  • 现在看浅复制

package com.whereta.prototype;

import com.alibaba.fastjson.JSON;

/**
 * Vincent 创建于 2016/4/18.
 * 浅复制:只是复制基本数据类型,引用类型还是指向同一个地址
 */
public class ShallowClone {
    public static void main(String[] args) throws CloneNotSupportedException {


        Company company=new Company();
        company.setName("海信科技");

        User user=new User();
        user.setAge(22);
        user.setName("小明");
        user.setCompany(company);


        Object clone = user.clone();


        User user1= (User) clone;
        //此处可以看出,与简单复制不同的是:克隆之后的对象与源对象引用地址不同
        System.out.println(user);
        System.out.println(clone);

        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(clone));

        System.out.println(user.getCompany());
        System.out.println(user1.getCompany());

        //此处可以看出,修改了公司名字,两个对象都修改了公司名字,所以引用的是同一个对象
        company.setName("sdfds");


        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(clone));

        //此处测试:修改基本数据类型只会修改当前对象,不会修改克隆对象
        user.setAge(34);

        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(clone));

    }
}
  • 输出结果:

com.whereta.prototype.User@6ef64f64
com.whereta.prototype.User@6cd66725
{"age":22,"company":{"name":"海信科技"},"name":"小明"}
{"age":22,"company":{"name":"海信科技"},"name":"小明"}
com.whereta.prototype.Company@2d75705e
com.whereta.prototype.Company@2d75705e
{"age":22,"company":{"name":"sdfds"},"name":"小明"}
{"age":22,"company":{"name":"sdfds"},"name":"小明"}
{"age":34,"company":{"name":"sdfds"},"name":"小明"}
{"age":22,"company":{"name":"sdfds"},"name":"小明"}
  • 从输出结果可以看出:克隆之后的对象与源对象指向了不同地址;但是引用对象(公司)还是指向了同一个地址,所以修改公司名字两个对象都会修改;但是修改基本类型数据不会修改克隆之后的对象数据


  • 深度克隆:

package com.whereta.prototype;

import com.alibaba.fastjson.JSON;

/**
 * Vincent 创建于 2016/4/18.
 * 深度复制:无论是基本数据类型还是引用类型,全部重新复制一份
 */
public class DeepClone {

    public static void main(String[] args) throws CloneNotSupportedException {
        Company company=new Company();
        company.setName("海信科技");

        DeepUser user=new DeepUser();
        user.setAge(22);
        user.setName("小明");
        user.setCompany(company);


        Object clone = user.clone();
        DeepUser user1= (DeepUser) clone;
        //此处可以看出,与简单复制不同的是:克隆之后的对象与源对象引用地址不同
        System.out.println(user);
        System.out.println(clone);

        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(clone));
        //此处可以看出引用对象地址也是不一样的
        System.out.println(user.getCompany());
        System.out.println(user1.getCompany());

        //此处可以看出,修改了公司名字,不会修改克隆之后的对象公司名字
        company.setName("sdfds");


        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(clone));

        //此处测试:修改基本数据类型只会修改当前对象,不会修改克隆对象
        user.setAge(34);

        System.out.println(JSON.toJSONString(user));
        System.out.println(JSON.toJSONString(clone));
    }

}
  • 输出结果:

com.whereta.prototype.DeepUser@3a5367af
com.whereta.prototype.DeepUser@1b033c7e
{"age":22,"company":{"name":"海信科技"},"name":"小明"}
{"age":22,"company":{"name":"海信科技"},"name":"小明"}
com.whereta.prototype.Company@71f84d01
com.whereta.prototype.Company@3e8f474f
{"age":22,"company":{"name":"sdfds"},"name":"小明"}
{"age":22,"company":{"name":"海信科技"},"name":"小明"}
{"age":34,"company":{"name":"sdfds"},"name":"小明"}
{"age":22,"company":{"name":"海信科技"},"name":"小明"}
  • 从输出结果可以看出:克隆之后的引用对象也是与源对象引用对象地址不一样,所以深度克隆是完全的克隆!!

总结:


优点:

  • 当创建新的对象实例较为复杂时,可以简化对象创建过程,通过复制一个已有实例可以提高实例的创建效率。

  • 扩展性较好,原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程。

  • 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品。

  • 可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。



参考文章:http://blog.csdn.net/yanbober/article/details/45363525

个人博客:http://www.whereta.com

© 著作权归作者所有

共有 人打赏支持
清尘V
粉丝 42
博文 107
码字总数 47780
作品 0
青岛
程序员

暂无文章

HashMap工作原理及实现

HashMap工作原理及实现 1. 概述 什么时候会使用HashMap?他有什么特点? 知道HashMap的工作原理吗? 知道get和put的原理吗? 知道hash的实现吗?为什么要这样实现? 如果HashMap的大小超过了...

傅小水water
11分钟前
0
0
swagger如何屏蔽某些接口,不对外公开--使用@ApiIgnore

@ApiIgnore@RestController@RequestMapping(value = "/i18nTest")public class I18nTestController {// @Resource// private LocaleMessageSourceService localeMessageSourceSe......

karma123
15分钟前
0
0
大数据技术学习,大数据处理为何选择Spark,而不是Hadoop

大数据处理为何选择Spark,而不是Hadoop。 一.基础知识 1.Spark Spark是一个用来实现快速而通用的集群计算的平台。 在速度方面,Spark扩展了广泛使用的MapReduce计算模型,而且高效地支持更多...

董黎明
22分钟前
0
0
Java程序员的书籍清单

我自己一路来,看过的书籍,都是经典,我自己也在不断地回溯,在这里分享给大家(排名不分先后,这里仅仅是我自己购买这些书籍的时间顺序排列): 《高效程序员的45个习惯 敏捷开发修炼之道》...

ChinaHYF
48分钟前
1
0
DeepMind 开源图神经网络的代码

用于支持论文《Relational inductive biases, deep learning, and graph networks》。 github A graph network takes a graph as input and returns a graph as output. The input graph has......

shengjuntu
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部