专栏首页泰斗贤若如原型模式(转载)

原型模式(转载)

目录

回到顶部

找工作难呐

  大家好,我原本是神剑山庄的铸剑师,名叫小赵,本来干的好好的,后来一时兴起,睡了三少爷的小姨子,与其一直提心吊胆,干脆来个逃之夭夭。

  但是,我也要吃饭的呀,工作也得找,神剑山庄去不得,还有断剑山庄、藏剑山庄、荡剑山庄、等等等等大型企业,说不定这次跳槽,能跳出个飞黄腾达!

  为了提高我投简历的准确性,我觉得简历要写的多样化,不能全写一模一样,比如说我的期望薪资不能写成一样,因为我希望能够根据目标企业的情况来投递合适薪资的简历,这样中标概率大一点。

  这是我的简历类:

public class Resume {
    private String name;
    private String position;
    private int salary;

    public String getName() {
        return name;
    }

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

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Resume{" +
                "name='" + name + '\'' +
                ", position='" + position + '\'' +
                ", salary=" + salary +
                '}';
    }
}

  现在,我正在熬夜写简历。。。。。

    public static void main(String[] args) {
        Resume resume1 = new Resume();
        resume1.setName("小赵");
        resume1.setPosition("高级铸剑工程师");
        resume1.setSalary(1000);

        Resume resume2 = new Resume();
        resume2.setName("小赵");
        resume2.setPosition("高级铸剑工程师");
        resume2.setSalary(1200);

        Resume resume3 = new Resume();
        resume2.setName("小赵");
        resume3.setPosition("高级铸剑工程师");
        resume3.setSalary(1500);
        //.....
    }

  当我写到20多份的时候,我已经睡着了。。。。。

  唉,找工作难啊。。。。。。

回到顶部

打印机跑起来

  第二天,我去万达广场买了个打印机回来,直接循环打印!

    public static void main(String[] args) {
        int num = 5;
        while (num > 0){
            Resume resume1 = new Resume();
            int salary = (int)(1000+Math.random()*(2000-1000+1));
            resume1.setName("小赵");
            resume1.setPosition("高级铸剑工程师");
            resume1.setSalary(salary);
            System.out.println(resume1.toString());
            num --;
        }
    }

输出:

Resume{name='小赵', position='高级铸剑工程师', salary=1389} Resume{name='小赵', position='高级铸剑工程师', salary=1383} Resume{name='小赵', position='高级铸剑工程师', salary=1345} Resume{name='小赵', position='高级铸剑工程师', salary=1446} Resume{name='小赵', position='高级铸剑工程师', salary=1221}

  先试了一下,打印5份简历,感觉没问题。

  有了这个打印机之后,我也接些私活,帮别人打印简历,生意越做越火,一个月后,我工作没找到,但打印机一天到晚倒是没停过。

  到了现在,我的打印机一天到晚要打印一百万张简历,每次打印都要耗电耗内存耗机器寿命,我的打印机已经报废了好几台,并且在不断的购买新的打印机。

  作为一个工程师,我决定要研究一下有没有更好的解决办法。

回到顶部

复印机跑起来

  听说Cloneable接口有个复印机可以用,我决定去试试,效果的好的话就把复印机装到打印机里面去,搞个多功能一体机。

  这是修改后的简历类:

public class Resume implements Cloneable{
    private String name;
    private String position;
    private int salary;

    public String getName() {
        return name;
    }

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

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    @Override
    protected Resume clone(){
        Resume resume = null;
        try{
            resume = (Resume) super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return resume;
    }

    @Override
    public String toString() {
        return "Resume{" +
                "name='" + name + '\'' +
                ", position='" + position + '\'' +
                ", salary=" + salary +
                '}';
    }
}

复印机跑起来:

    public static void main(String[] args) {
        int num = 5;
        Resume resume = new Resume();
        while (num > 0){
            Resume resume1 = resume.clone();
            int salary = (int)(1000+Math.random()*(2000-1000+1));
            resume1.setName("小赵");
            resume1.setPosition("高级铸剑工程师");
            resume1.setSalary(salary);
            System.out.println(resume1.toString());
            num --;
        }
    }

和打印机的效果是一样的,但是这里事实上只打印了一次,然后其他的都是拷贝复印出来的。

  。。。。。。

  多年之后,我才恍然大悟,当初我用复印机复印简历的做法,其实就是设计模式中的原型模式。

回到顶部

原型模式的使用场景

  大体上有两种使用场景

  1.在需要一个类的大量对象的时候,使用原型模式是最佳选择,因为原型模式是在内存中对这个对象进行拷贝,要比直接new这个对象性能要好很多,在这种情况下,需要的对象越多,原型模式体现出的优点越明显。

  2.如果一个对象的初始化需要很多其他对象的数据准备或其他资源的繁琐计算,那么可以使用原型模式。

  3.当需要一个对象的大量公共信息,少量字段进行个性化设置的时候,也可以使用原型模式拷贝出现有对象的副本进行加工处理。

回到顶部

构造函数的问题

  写个程序测一下构造函数:

public class AAA implements Cloneable {
    public AAA() {
        System.out.println("我来了。。");
    }

    @Override
    protected AAA clone(){
        AAA aaa = null;
        try {
            aaa = (AAA) super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return aaa;
    }
}
    public static void main(String[] args) {
        AAA aaa = new AAA();
        AAA aaa1 = aaa.clone();
    }

输出:

我来了。。

  就输出一次,这里可以证明对象拷贝的时候构造函数是不会执行的,原因在于拷贝是直接在堆中进行,这其实也可以理解,new的时候,JVM要走一趟类加载流程,这个流程非常麻烦,在类加载流程中会调用构造函数,最后生成的对象会放到堆中,而拷贝就是直接拷贝堆中的现成的二进制对象,然后重新一个分配内存块。

回到顶部

浅拷贝

  上个例子展示什么是浅拷贝

  这里新加一个类BBB:

public class BBB{
    private String name;

    public String getName() {
        return name;
    }

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

  AAA类修改为:

public class AAA implements Cloneable {
    private BBB bbb = new BBB();

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

    public String getName() {
        return this.bbb.getName();
    }

    @Override
    protected AAA clone(){
        AAA aaa = null;
        try {
            aaa = (AAA) super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return aaa;
    }
}

  main方法:

    public static void main(String[] args) {
        AAA aaa = new AAA();
        aaa.setName("张三");
        System.out.println(aaa.getName());

        AAA aaa1 = aaa.clone();
        System.out.println(aaa1.getName());
    }

输出:

张三 张三

  这种情况就是浅拷贝,java只拷贝你指定的对象,至于你指定的对象里面的别的对象,它不拷贝,还是把引用给你,共享变量,这是一种非常不安全的方式,需要特别注意。

  内部的数组和引用对象不会拷贝,其他的原始基本类型和String类型会被拷贝。

  如果要实现深拷贝呢?

  那就只能在AAA的clone方法里把BBB实例化出来了:

    @Override
    protected AAA clone(){
        AAA aaa = null;
        try {
            aaa = (AAA) super.clone();
            aaa.bbb = new BBB();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return aaa;
    }

 转载自https://www.cnblogs.com/fengyumeng/p/10646487.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何优雅的构建排序公式

    最近的一个项目中的需求要对一堆元素进行排序,排序的依据是元素在页面上面的坐标位置,然后按照顺序给所有元素一个编号。如下图所示:

    用户3158888
  • Gatsby入门指南—使用GraphQL解析Markdown(2)

    GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户...

    前端大彬哥
  • 使用PHPStorm+Composer快速初始化项目

    使用PHPStorm创建项目,这个我就不再废话了。 无论你是通过版本控制系统checkout一个项目;还是直接 create一个本地项目;或者create一个...

    luxixing
  • JavaScript 数组去重的多种方法原理详解

    数组去重,这是一个面试经常会遇见的问题,网上讲数组去重的文章也是特别的多,但是我们依旧来讲讲数组去重,这篇文章比较适合于接触过一段时间的JavaScript的初...

    FEWY
  • 大型网站背后的高性能系统架构设计

    CDN 的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户已最快速度获取数据,即所谓网络访问第一跳。

    李红
  • 简单说 如何做一个chrome 去广告插件

    这次我们先来简单接触一下,了解一点入门知识,先做一个简单的demo,就先去除一下CSDN网页上的广告。

    FEWY
  • ARC内存管理中容易忽略的问题

    看到好几篇文章都在说这道面试题,字符串差不多是每个高级语言必有的,在实际项目中也的确是使用的最多类型之一。本文就以此题开始我们的内存管理的讨论。

    羊羽shine
  • Gatsby入门指南—添加博客内容页(4)

    注意,这里跟前面不一样了,我用gatsby-node.js这个文件去提供数据,没有什么为什么,规定,照做就好。

    前端大彬哥
  • 调试你的node.js程序(一)

    使用node.js开发已经有一段时间了,最开始的调试是使用工具node-inspector;不过node-inspector已经很长一段时间不能用了。 现在要调...

    用户3158888
  • JavaScript 转换数字为整数的方法

    本文将会列举并说明JavaScript 把一个number(或者numerical的对象)转换成一个整数相关方法。

    用户3158888

扫码关注云+社区

领取腾讯云代金券