乐趣区

java设计模式原型模式浅拷贝和深拷贝

【java_设计模式】原型模式、浅拷贝和深拷贝
应用场景
需要同一个类的多个不同对象完成业务操作,群发 email,需要多个 Mail 类的对象
好处:提高性能
[Java] 纯文本查看 复制代码
?

public static void main(String[] args) throws CloneNotSupportedException {

   Mail mail = new Mail();
   mail.setContent("初始化模板");
   for(int i=0; i<10; i++) {
        // 创建 10 个 Mail 的对象进行发邮件的操作,使用原型模式加快性能
       Mail mailTemp = (Mail) mail.clone();
       mailTemp.setName("第" + i + "个克隆出来的对象");
       // 使用克隆采用的是二进制的拷贝,效率比直接 new 高很多
   }
   // 不改变原来的 Mail
   MailUtil.saveOriginMailRecord(mail);

}

实现
[Java] 纯文本查看 复制代码
?

// 省略 get set 方法
public class Mail implements Cloneable{

private String name;
private String address;
private String content;
public Mail() {System.out.println("Mail Class Constructor");
}

/**
 * 记得重写方法
 * @return
 * @throws CloneNotSupportedException
 */
@Override
protected Object clone() throws CloneNotSupportedException {return super.clone();
}

@Override
public String toString() {
    return "Mail{" +
            "name='" + name + '\'' +
            ", address='" + address + '\'' +
            ", content='" + content + '\'' +
            '}';
}

}

[Java] 纯文本查看 复制代码
?

public class MailUtil {

public static void sendMail(Mail mail) {String outputContent = "向 {0} 同学,邮件地址{1},邮件内容:{2},发送成功";
    System.out.println(MessageFormat.format(outputContent, mail.getName(),mail.getAddress(),mail.getContent()));
}

public static void saveOriginMailRecord(Mail mail) {System.out.println("存储 originMail 记录,originMail:" + mail.getContent());
}

}

原理

原型模式的本质是类继承 Clonable 接口,重写 clone 方法。clone 的底层是使用二进制拷贝,需要多个对象的时候可以用该方法取代多次 new,提高性能。

修改原对象的成员变量,可能会同时修改克隆出来的对象。避免这种坑即使用深拷贝。
不重写 clone 方法,默认使用浅拷贝

[Java] 纯文本查看 复制代码
?

public class Pig implements Cloneable{

private String name;
// 引用对象
private Date birthday;
 
// 默认的 clone 方法,不会修改引用对象的指向,即拷贝出来的对象中 birthday 引用指向的是同一块内存区域
@Override
protected Object clone() throws CloneNotSupportedException {Pig pig = (Pig)super.clone();

    // 深拷贝,有引用对象的时候需要重写 clone()方法
    pig.birthday = (Date)pig.birthday.clone();
    return pig;
}

}

拓展
原型模式和单例模式结合的时候,注意修改 clone 方法
1. 极端场景

[Java] 纯文本查看 复制代码
?

<font style=”color:rgb(79, 79, 79)”><font face=”&quot”><font style=”font-size:16px”>// step 2 克隆破坏单例

    HungrySingleton hungrySingleton = HungrySingleton.getInstance();
    Method method = hungrySingleton.getClass().getDeclaredMethod("clone");
    method.setAccessible(true);
    HungrySingleton cloneHungrySingleton = (HungrySingleton) method.invoke(hungrySingleton);
    System.out.println(hungrySingleton);
    System.out.println(cloneHungrySingleton);

</font></font></font>
2. 关键代码

[Java] 纯文本查看 复制代码
?

<font style=”color:rgb(79, 79, 79)”><font face=”&quot”><font style=”font-size:16px”> /**

 * 单例模式下使用的 clone 方法, 防止克隆破坏就要修改方法实现
 * @return
 * @throws CloneNotSupportedException
 */
@Override
protected Object clone() throws CloneNotSupportedException {return getInstance();
}</font></font></font>

作者:Ch.yang
来源:CSDN
原文:https://blog.csdn.net/chengha…
版权声明:本文为博主原创文章,转载请附上博文链接!

退出移动版