1    课堂演练

1.1  super.toString 作用

1.2  为什么要使用克隆方法呢

2    代码解析

2.1  代码解析1(使用原型模式之前)

2.2  代码解析2(使用原型模式默认方式(浅克隆))

2.3  代码解析3(一种常用原型模式)

2.4  代码解析4(浅克隆的弊端)

2.5  代码解析5(深克隆实现)

 

1    课堂演练

1.1  super.toString 作用

打印出对象的内存地址

 

1.2  为什么要使用克隆方法呢

有一些场景需要继续使用这个对象,只不过咱们简化了一些。其实这个场景,一直用同一个对象也可以,但是不符合面向对象的写法。一个对象和另外一个对象尽量独立存在

 

2    代码解析

2.1  代码解析1(使用原型模式之前)

需求:

 

邮件类:

package com.geely.design.pattern.creational.prototype;

public class Mail {
    private String name;
    private String emailAddress;
    private String content;

    /**
     * 1    添加初始化方法,目的是为了一会儿和克隆方法 出来的对象,作对比。
     *      查看克隆出来的对象是否是此初始化出来的。
     */
    public Mail(){
        System.out.println("Mail Class Constructor");
    }

    /**
     * 2    为打印方便,添加toString方法
     * @return
     */
    @Override
    public String toString() {
        return "Mail{" +
                "name='" + name + '\'' +
                ", emailAddress='" + emailAddress + '\'' +
                ", content='" + content + '\'' +
                '}';
    }

    /**
     * 3    以下是get和set方法
     * @return
     */
    public String getName() {
        return name;
    }

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

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

 

邮件工具类:

package com.geely.design.pattern.creational.prototype;

import java.text.MessageFormat;

/**
 * 邮件工具类,实现发送邮件和保存邮件初始化模版的功能
 */
public class MailUtil {

    /**
     * 1    发送邮件功能的实现
     * 重点:  占位符赋值的实现
     * @param mail
     */
    public static void sendMail(Mail mail){
        String sOutPutContent = "向{0}同学发送邮件内容为{1},邮件地址为:{2}";
        System.out.println(MessageFormat.format(sOutPutContent,mail.getName(),mail.getContent(),mail.getEmailAddress()));
    }

    /**
     * 2    保存日志记录
     */
    public static void saveOriginMail(Mail mail){
        System.out.println("邮件内容为"+mail.getContent());
    }
}

 

测试类:

package com.geely.design.pattern.creational.prototype;

/**
 * 测试类:
 */
public class Test {

    /**
     * 1    测试使用原型模式(克隆之前)
     * @param args
     */
    public static void main(String [] args){
        Mail mail = new Mail();
        mail.setContent("初始化模版");

        for(int i = 0;i < 10;i++){
            mail.setName("姓名"+i);
            mail.setContent("内容"+i);
            mail.setEmailAddress(i+"@imooc.com");
            MailUtil.sendMail(mail);
        }
        MailUtil.saveOriginMail(mail);
    }

}

 

打印日志:

Mail Class Constructor
向姓名0同学发送邮件内容为内容0,邮件地址为:0@imooc.com
向姓名1同学发送邮件内容为内容1,邮件地址为:1@imooc.com
向姓名2同学发送邮件内容为内容2,邮件地址为:2@imooc.com
向姓名3同学发送邮件内容为内容3,邮件地址为:3@imooc.com
向姓名4同学发送邮件内容为内容4,邮件地址为:4@imooc.com
向姓名5同学发送邮件内容为内容5,邮件地址为:5@imooc.com
向姓名6同学发送邮件内容为内容6,邮件地址为:6@imooc.com
向姓名7同学发送邮件内容为内容7,邮件地址为:7@imooc.com
向姓名8同学发送邮件内容为内容8,邮件地址为:8@imooc.com
向姓名9同学发送邮件内容为内容9,邮件地址为:9@imooc.com
邮件内容为内容9

Process finished with exit code 0

 

2.2  代码解析2(使用原型模式默认方式(浅克隆))

邮件类:

package com.geely.design.pattern.creational.prototype;
/*
*  只有实现clonable接口,才能调用clone方法
*/
public class Mail implements Cloneable{ private String name; private String emailAddress; private String content; /** * 4 添加浅克隆方法 * @return * @throws CloneNotSupportedException */ @Override protected Object clone() throws CloneNotSupportedException { System.out.println("调用克隆方法"); return super.clone(); } /** * 1 添加初始化方法,目的是为了一会儿和克隆方法 出来的对象,作对比。 * 查看克隆出来的对象是否是此初始化出来的。 */ public Mail(){ System.out.println("Mail Class Constructor"); } /** * 2 为打印方便,添加toString方法
   * 添加super.toString方法是为了打印内存地址,比较克隆的对象内存地址和初始化的对象内存地址是否一致    * 以及克隆对象之间内存地址是否一致
*
@return */ @Override public String toString() { return "Mail{" + "name='" + name + '\'' + ", emailAddress='" + emailAddress + '\'' + ", content='" + content + '\'' + '}'+super.toString(); } /** * 3 以下是get和set方法 * @return */ public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }

 

邮件工具类:

package com.geely.design.pattern.creational.prototype;

import java.text.MessageFormat;

/**
 * 邮件工具类,实现发送邮件和保存邮件初始化模版的功能
 */
public class MailUtil {

    /**
     * 1    发送邮件功能的实现
     * 重点:  占位符赋值的实现
     * @param mail
     */
    public static void sendMail(Mail mail){
        String sOutPutContent = "向{0}同学发送邮件内容为{1},邮件地址为:{2}";
        System.out.println(MessageFormat.format(sOutPutContent,mail.getName(),mail.getContent(),mail.getEmailAddress()));
    }

    /**
     * 2    保存日志记录
     */
    public static void saveOriginMail(Mail mail){
        System.out.println("邮件内容为"+mail.getContent()+mail.getContent());
    }
}

 

测试类:

package com.geely.design.pattern.creational.prototype;

/**
 * 测试类:
 */
public class Test {

    /**
     * 1    测试使用原型模式(克隆之前)
     * @param args
     */
    public static void main(String [] args) throws CloneNotSupportedException {
        Mail mail = new Mail();
        mail.setContent("初始化模版");
        System.out.println("初始化对象内存地址"+mail);

        for(int i = 0;i < 10;i++){
            Mail mailTemp = (Mail) mail.clone();
            mailTemp.setName("姓名"+i);
            mailTemp.setContent("内容"+i);
            mailTemp.setEmailAddress(i+"@imooc.com");
            MailUtil.sendMail(mailTemp);
            System.out.println("克隆对象"+i+"内存地址"+mailTemp);
        }
        MailUtil.saveOriginMail(mail);
    }

}

 

打印日志:

"C:\Program Files\Java\jdk1.7.0_79\bin\java.exe" "-javaagent:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\lib\idea_rt.jar=3318:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;F:\xiangmu3\Xin\Idea\design_pattern\target\classes" com.geely.design.pattern.creational.prototype.Test
Mail Class Constructor
初始化对象内存地址Mail{name='null', emailAddress='null', content='初始化模版'}com.geely.design.pattern.creational.prototype.Mail@52a7b7ff
调用克隆方法
向姓名0同学发送邮件内容为内容0,邮件地址为:0@imooc.com
克隆对象0内存地址Mail{name='姓名0', emailAddress='0@imooc.com', content='内容0'}com.geely.design.pattern.creational.prototype.Mail@49164555
调用克隆方法
向姓名1同学发送邮件内容为内容1,邮件地址为:1@imooc.com
克隆对象1内存地址Mail{name='姓名1', emailAddress='1@imooc.com', content='内容1'}com.geely.design.pattern.creational.prototype.Mail@5521f4ef
调用克隆方法
向姓名2同学发送邮件内容为内容2,邮件地址为:2@imooc.com
克隆对象2内存地址Mail{name='姓名2', emailAddress='2@imooc.com', content='内容2'}com.geely.design.pattern.creational.prototype.Mail@2857a293
调用克隆方法
向姓名3同学发送邮件内容为内容3,邮件地址为:3@imooc.com
克隆对象3内存地址Mail{name='姓名3', emailAddress='3@imooc.com', content='内容3'}com.geely.design.pattern.creational.prototype.Mail@11727596
调用克隆方法
向姓名4同学发送邮件内容为内容4,邮件地址为:4@imooc.com
克隆对象4内存地址Mail{name='姓名4', emailAddress='4@imooc.com', content='内容4'}com.geely.design.pattern.creational.prototype.Mail@7185d3cc
调用克隆方法
向姓名5同学发送邮件内容为内容5,邮件地址为:5@imooc.com
克隆对象5内存地址Mail{name='姓名5', emailAddress='5@imooc.com', content='内容5'}com.geely.design.pattern.creational.prototype.Mail@914304e
调用克隆方法
向姓名6同学发送邮件内容为内容6,邮件地址为:6@imooc.com
克隆对象6内存地址Mail{name='姓名6', emailAddress='6@imooc.com', content='内容6'}com.geely.design.pattern.creational.prototype.Mail@c6f558a
调用克隆方法
向姓名7同学发送邮件内容为内容7,邮件地址为:7@imooc.com
克隆对象7内存地址Mail{name='姓名7', emailAddress='7@imooc.com', content='内容7'}com.geely.design.pattern.creational.prototype.Mail@112f8578
调用克隆方法
向姓名8同学发送邮件内容为内容8,邮件地址为:8@imooc.com
克隆对象8内存地址Mail{name='姓名8', emailAddress='8@imooc.com', content='内容8'}com.geely.design.pattern.creational.prototype.Mail@771c9fcc
调用克隆方法
向姓名9同学发送邮件内容为内容9,邮件地址为:9@imooc.com
克隆对象9内存地址Mail{name='姓名9', emailAddress='9@imooc.com', content='内容9'}com.geely.design.pattern.creational.prototype.Mail@4c0d39ac
邮件内容为初始化模版初始化模版

Process finished with exit code 0

 

2.3  代码解析3(一种常用原型模式)

实体类:

 

package com.geely.design.pattern.creational.prototype.abstractprototype;

/**
 * 一种常用的原型模式
 * 通过抽象类来实现原型模式
 */
public abstract class A implements Cloneable{

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

 

 

 

继承类:

 

package com.geely.design.pattern.creational.prototype.abstractprototype;

/**
 * 继承A类,直接调用clone接口
 */
public class B extends A{

    public static void main(String [] args){
        B b = new B();
        try {
            b.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            System.out.println("处理异常");
        }
    }
}

 

 

 

2.4  代码解析4(浅克隆的弊端)

实现功能:

小猪佩奇1克隆出新的对象小猪佩奇2,修改佩奇1的生日,佩奇2的生日保持不变

 

实体类:

package com.geely.design.pattern.creational.prototype;

import java.util.Date;

public class Pig implements Cloneable{
    private String name;
    private Date birthday;

    /**
     * 4    添加有参构造方法,方便测试类赋值
     * @param name
     * @param birthday
     */
    public Pig(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    /**
     * 3    添加克隆方法
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    /**
     * 2    添加toString方法,方便测试
     * @return
     */
    @Override
    public String toString() {
        return "Pig{" +
                "name='" + name + '\'' +
                ", birthday=" + birthday +super.toString()+
                '}';
    }

    /**
     * 1    getset方法
     * @return
     */
    public String getName() {
        return name;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

 

 

测试类:

package com.geely.design.pattern.creational.prototype;

import java.util.Date;

public class Test2 {
    public static void main(String [] args){
        try {
            Date date1 = new Date();
            Pig pig1 = new Pig("peiqi",date1);
            Pig pig2 = (Pig) pig1.clone();
            System.out.println(pig1);
            System.out.println(pig2);


            //预期修改pig1的生日,没想到pig2的生日也改了
            pig1.getBirthday().setTime(0L);
            System.out.println(pig1);
            System.out.println(pig2);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            System.out.println("出现异常");
        }
    }
}

 

 

打印日志:

 

"C:\Program Files\Java\jdk1.7.0_79\bin\java.exe" "-javaagent:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\lib\idea_rt.jar=8024:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;F:\xiangmu3\Xin\Idea\design_pattern\target\classes" com.geely.design.pattern.creational.prototype.Test2
Pig{name='peiqi', birthday=Thu Sep 05 05:44:20 CST 2019com.geely.design.pattern.creational.prototype.Pig@1bfdfa36}
Pig{name='peiqi', birthday=Thu Sep 05 05:44:20 CST 2019com.geely.design.pattern.creational.prototype.Pig@3f35fd95}
Pig{name='peiqi', birthday=Thu Jan 01 08:00:00 CST 1970com.geely.design.pattern.creational.prototype.Pig@1bfdfa36}
Pig{name='peiqi', birthday=Thu Jan 01 08:00:00 CST 1970com.geely.design.pattern.creational.prototype.Pig@3f35fd95}

Process finished with exit code 0

 

 

2.5  代码解析5(深克隆实现)

实体类:

package com.geely.design.pattern.creational.prototype;

import java.util.Date;

public class Pig implements Cloneable{
    private String name;
    private Date birthday;

    /**
     * 4    添加有参构造方法,方便测试类赋值
     * @param name
     * @param birthday
     */
    public Pig(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    /**
     * 3    添加克隆方法
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Pig pig = (Pig) super.clone();
        //深克隆
        pig.birthday = (Date) pig.birthday.clone();
        return pig;
    }

    /**
     * 2    添加toString方法,方便测试
     * @return
     */
    @Override
    public String toString() {
        return "Pig{" +
                "name='" + name + '\'' +
                ", birthday=" + birthday +super.toString()+
                '}';
    }

    /**
     * 1    getset方法
     * @return
     */
    public String getName() {
        return name;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

 

 

 

测试类:(同2.4)

package com.geely.design.pattern.creational.prototype;

import java.util.Date;

public class Test2 {
    public static void main(String [] args){
        try {
            Date date1 = new Date();
            Pig pig1 = new Pig("peiqi",date1);
            Pig pig2 = (Pig) pig1.clone();
            System.out.println(pig1);
            System.out.println(pig2);


            //预期修改pig1的生日,没想到pig2的生日也改了
            pig1.getBirthday().setTime(0L);
            System.out.println(pig1);
            System.out.println(pig2);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            System.out.println("出现异常");
        }
    }
}

 

 

打印日志:

"C:\Program Files\Java\jdk1.7.0_79\bin\java.exe" "-javaagent:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\lib\idea_rt.jar=8433:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;F:\xiangmu3\Xin\Idea\design_pattern\target\classes" com.geely.design.pattern.creational.prototype.Test2
Pig{name='peiqi', birthday=Thu Sep 05 06:02:15 CST 2019com.geely.design.pattern.creational.prototype.Pig@1bfdfa36}
Pig{name='peiqi', birthday=Thu Sep 05 06:02:15 CST 2019com.geely.design.pattern.creational.prototype.Pig@3f35fd95}
Pig{name='peiqi', birthday=Thu Jan 01 08:00:00 CST 1970com.geely.design.pattern.creational.prototype.Pig@1bfdfa36}
Pig{name='peiqi', birthday=Thu Sep 05 06:02:15 CST 2019com.geely.design.pattern.creational.prototype.Pig@3f35fd95}

Process finished with exit code 0

 

posted on 2019-09-04 06:03  菜鸟乙  阅读(164)  评论(0编辑  收藏  举报