文档章节

原型模式

清尘V
 清尘V
发布于 2016/04/18 09:26
字数 1394
阅读 14
收藏 0
点赞 1
评论 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
粉丝 43
博文 107
码字总数 47780
作品 0
青岛
程序员

暂无相关文章

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 52分钟前 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 今天 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

VS中使用X64汇编

需要注意的是,在X86项目中,可以使用__asm{}来嵌入汇编代码,但是在X64项目中,再也不能使用__asm{}来编写嵌入式汇编程序了,必须使用专门的.asm汇编文件来编写相应的汇编代码,然后在其它地...

simpower ⋅ 今天 ⋅ 0

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部