设计模式之原型模式【选用鸣人影分身阐述】

爱⌒轻易说出口 提交于 2020-07-29 06:10:19
       一生猿,一世猿。
                    —— 猿医生·yys 

                         

 

目录

一、前言

二、简介

三、原型模式 - 浅克隆

 四、原型模式 - 深克隆

 

 

 

一、前言

       上篇 设计模式之工厂模式【选用修仙小说功法阐述】得到 CSDN官方大大以及各位猿友的推崇,小主很是倍感荣幸。

       今天呢 (2020.05.22),利用【齐天大圣拔毫毛】【鸣人多重影分身】两个案例来阐述下 设计模式之原型模式

       在此,记录一下,分享给大家。

 

 

二、简介

       姓名:原型模式

       英文名:Prototype Pattern

       个人介绍:原型模式(prototype pattern)是指用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

                         原型模式属于创建型的设计模式。

                         原型模式分为 浅克隆、深克隆。

       特长爱好:1.类初始化消耗资源太多;

                         2.new 对象需要非常繁琐的过程 (数据准备、访问权限);

                         3.构造函数复杂;

                         4.循环中需要生成大量对象;

 

       相信大家读到这里... ...用一首最近流行的网红洗脑神曲,“小朋友你是否有很多问号???”                   

                                                                                             

 

       不过...大家不要慌.... 按照小主的个人习惯,是时候上案例了,记得千万不要走神,车要开了。。

 

 

三、原型模式 - 浅克隆

 

       “猴哥,猴哥”,

       “你真了不得”,

       “五行大山压不住你”,

       “蹦出个孙行者”,

       ... ...  

       “拔一根毫毛”,

       “吹出猴万个”,

       ... ...  

       

 

       一首儿时曲,忆起童年往事 ~ 越长大越孤单 ~

       岁月的洪流,卷走了青春,卷走了年华,剩下的只是一个被岁月刻下深深印痕的伤痕累累的躯壳,和一颗沧桑的心。

     

       咳 咳 ~ 一不小心,来了波醉酒驾驶,哈哈 ~

       言归正传 ,大家都知道齐天大圣,手持金箍棒,拥有七十二变,拔一根毫毛,可以吹出千万个猴子猴孙。

       接下来 小主将采用 【齐天大圣拔毫毛】的案例来阐述原型模式之 浅克隆方式: 

 

 

       首先,定义一个猴子的  Monkey 类:

/**
 * 原型模式 - 浅克隆
 *      猴子类
 * @author yys
 */
@Getter
@Setter
// @Data (不使用 @Data,会重写toString()方法)
public class Monkey {

    private int height;

    private int width;

}

        接下来,定义金箍棒  JingGuBang 类:

/**
 * 原型模式 - 浅克隆
 *      金箍棒
 * @author yys
 */
@Getter
@Setter
public class JinGuBang {

    private float h = 99;

    private float w = 9;

    public void big() {
        this.h *= 10;
        this.w *= 10;
    }

    public void small() {
        this.h /= 2;
        this.w /= 2;
    }

}

         接下来,定义齐天大圣  QiTiDaSheng 类 - < 原型对象 >:

/**
 * 原型模式 - 浅克隆(原型对象)
 *      齐天大圣类
 * @author yys
 */
@Getter
@Setter
public class QiTianDaSheng extends Monkey implements Cloneable {

    private JinGuBang jinGuBang;

    public QiTianDaSheng1(JinGuBang jinGuBang) {
        this.jinGuBang = jinGuBang;
    }

    // 重写克隆方法
    @Override
    protected Object clone() {
        try {
            Object clone = super.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone();
    }

    // 浅克隆实现方式:
    //  1.需实现 Cloneable接口
    //  2.重写克隆方法

}

      原型模式 - 浅克隆 测试类及测试结果: 

/**
 * 原型模式 - 浅克隆
 *      Test
 * @author yys
 */
public class CloneTest {

    public static void main(String[] args) {
        try {

            // 创建原型对象
            QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(new JinGuBang()); // 传入金箍棒
            qiTianDaSheng.setWidth(10);
            qiTianDaSheng.setHeight(100);
            System.out.println("原型对象:" + qiTianDaSheng);

            // 开始克隆 - 浅克隆
            QiTianDaSheng cloneQiTianDaSheng = (QiTianDaSheng) qiTianDaSheng.clone();
            System.out.println("克隆对象:" + cloneQiTianDaSheng);

            // clone start compare
            System.out.println("\n原型对象中的引用类型地址值:" + qiTianDaSheng.getJinGuBang());
            System.out.println("克隆对象中的引用类型地址值:" + cloneQiTianDaSheng.getJinGuBang());
            System.out.println("原型对象引用类型地址值 compare 克隆对象引用类型地址值:" + (qiTianDaSheng.getJinGuBang() == cloneQiTianDaSheng.getJinGuBang()));

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

                  

      原型模式 - 浅克隆 总结:

                                

 

      从测试结果以及上图可以清楚看出,浅克隆只是完整的复制了值类型数据,而引用对象仍然指向原来的对象,意味着复制的不是值,而是引用的地址。

      在实际开发中,往往我们需要的是完整的复制原型对象(值类型 and 引用类型)。

      显然,浅克隆是无法满足我们日常的需求,这时候,深克隆方式就该闪亮登场了...   

       

 

 

 四、原型模式 - 深克隆

                       

 

       接下来 小主将采用 【鸣人多重影分身术】的案例来阐述原型模式之 深克隆方式 

 

       定义一个(原型对象)鸣人  Naruto 类:

/**
 * 深克隆(原型对象)
 *      鸣人类
 * @author yys
 */
@Getter
@Setter
public class Naruto implements Cloneable, Serializable { // 重点:实现序列化接口

    private String name;

    private int age;

    private List ninjutsu; // 忍术集合


    /**
     * 深克隆方法
     * @return
     */
    public Object deepClone() {
        try {

            // write
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            // read
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            Naruto clone = (Naruto) ois.readObject();

            // close stream
            bos.close();
            oos.close();
            bis.close();
            ois.close();

            // return
            return clone;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 重写克隆方法
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return deepClone();
    }

    public Naruto(String name, int age) {
        this.name = name;
        this.age = age;

        // 忍术
        this.ninjutsu = new ArrayList<Object>();
        this.ninjutsu.add("多重影分身");
        this.ninjutsu.add("风遁·螺旋手里剑");
        this.ninjutsu.add("色诱之术...");

    }

    // 深克隆实现方式:
    //  1.原型对象需实现 Serializable接口

}

       原型模式 - 深克隆 测试类及测试结果: 

/**
 * 深克隆
 *      Test
 * @author yys
 */
public class CloneTest {

    public static void main(String[] args) {
        try {

            // 创建原型对象
            Naruto naruto = new Naruto("漩涡鸣人", 16);
            System.out.println("原型对象:" + naruto);

            // 开始克隆 - 深克隆
            Naruto cloneNaruto = (Naruto) naruto.clone();
            System.out.println("克隆对象:" + cloneNaruto);

            // clone start compare
            System.out.println("\n原型对象中的引用类型值:" + naruto.getNinjutsu());
            System.out.println("克隆对象中的引用类型值:" + cloneNaruto.getNinjutsu());
            System.out.println("原型对象引用类型地址值 compare 克隆对象引用类型地址值:" + (naruto.getNinjutsu() == cloneNaruto.getNinjutsu()));

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

    }

}

                         

      原型模式 - 深克隆 总结:

                                

 

      从测试结果以及上图可以清楚看出,深克隆完整的复制了原型对象;值类型完全copy、引用类型一样完全copy。

 

      这个时候,相信结合上述简介中的特长爱好(原型模式的适用场景)的你,又将码出新高度 ,码出新逼格 ~ 

      最后,都看到这里了,顺手点个赞,加个收藏吧 ~  

 

 

                       Now ~ ~ ~写到这里,就写完了,如果有幸帮助到你,请记得关注我,共同一起见证我们的成长

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!