深克隆与浅克隆

This commit is contained in:
2018-09-25 21:50:08 +08:00
parent 651251457c
commit 580b5cd97c
3 changed files with 193 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
package top.fjy8018.designpattern.pattern.creational.prototype.clone;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
* 原型模式:使用原型实例指定待创建对象的类型,并且通过<strong>复制</strong>这个原型来创建新的对象
* 适用于初始化对象复杂的场景
* <p>
* 邮件——深克隆实现
*
* @author F嘉阳
* @date 2018-09-25 20:39
*/
@Slf4j
@Getter
@Setter
public class CMailAfter implements Cloneable {
private String name;
/**
* String类型本身是不可变不需要重新实现深克隆
*/
private Date date;
private String content;
public CMailAfter() throws InterruptedException {
// 模拟调用构造器需要复杂过程
Thread.sleep(100);
log.debug(this.getClass().getSimpleName() + "构造器调用");
}
/**
* 带上父类toString方法查看是否为同一个对象
*
* @return
*/
@Override
public String toString() {
return "CMailAfter{" +
"name='" + name + '\'' +
", date=" + date +
", content='" + content + '\'' +
'}';
}
/**
* 调用克隆函数不需要调用构造器以此加快实例化速度
* 通过调用每个属性的克隆方法实现深克隆
*
* @return
* @throws CloneNotSupportedException
*/
@Override
public Object clone() throws CloneNotSupportedException {
CMailAfter mail = (CMailAfter) super.clone();
// 单独对Date进行克隆
mail.date = (Date) date.clone();
return mail;
}
}

View File

@@ -0,0 +1,58 @@
package top.fjy8018.designpattern.pattern.creational.prototype.clone;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
/**
* 原型模式:使用原型实例指定待创建对象的类型,并且通过<strong>复制</strong>这个原型来创建新的对象
* 适用于初始化对象复杂的场景
* <p>
* 邮件
*
* @author F嘉阳
* @date 2018-09-25 20:39
*/
@Slf4j
@Getter
@Setter
public class CMailBefore implements Cloneable {
private String name;
private Date date;
private String content;
public CMailBefore() throws InterruptedException {
// 模拟调用构造器需要复杂过程
Thread.sleep(100);
log.debug(this.getClass().getSimpleName() + "构造器调用");
}
/**
* 带上父类toString方法查看是否为同一个对象
*
* @return
*/
@Override
public String toString() {
return "CMailBefore{" +
"name='" + name + '\'' +
", date=" + date +
", content='" + content + '\'' +
'}';
}
/**
* 调用克隆函数不需要调用构造器以此加快实例化速度
* 通过调用每个属性的克隆方法实现深克隆
*
* @return
* @throws CloneNotSupportedException
*/
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View File

@@ -6,6 +6,10 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import top.fjy8018.designpattern.pattern.creational.prototype.after.AMail; import top.fjy8018.designpattern.pattern.creational.prototype.after.AMail;
import top.fjy8018.designpattern.pattern.creational.prototype.after.AMailUtil; import top.fjy8018.designpattern.pattern.creational.prototype.after.AMailUtil;
import top.fjy8018.designpattern.pattern.creational.prototype.clone.CMailAfter;
import top.fjy8018.designpattern.pattern.creational.prototype.clone.CMailBefore;
import java.util.Date;
@Slf4j @Slf4j
class BMailTest { class BMailTest {
@@ -66,6 +70,73 @@ class BMailTest {
} }
// 本意希望在发送完所有邮件后保存开始的正文 // 本意希望在发送完所有邮件后保存开始的正文
AMailUtil.saveOriginMail(mail); AMailUtil.saveOriginMail(mail);
}
/**
* 由于String不可变性保证其稳定性而Date没有单独进行属性克隆导致
* <p>
* output
* ===
* CMailBefore构造器调用
* 15d0c81b CMailBefore{name='原始', date=Thu Jan 01 08:00:00 CST 1970, content='原始正文'}
* 4b1c1ea0 CMailBefore{name='原始', date=Thu Jan 01 08:00:00 CST 1970, content='原始正文'}
* ===============
* 15d0c81b CMailBefore{name='更新', date=Sun Sep 09 09:46:39 CST 2001, content='原始正文'}
* 4b1c1ea0 CMailBefore{name='原始', date=Sun Sep 09 09:46:39 CST 2001, content='原始正文'}
* 耗时109ms
* ===
*
* @throws Exception
*/
@Test
void cloneTestBefore() throws Exception {
CMailBefore mail1 = new CMailBefore();
mail1.setName("原始");
mail1.setContent("原始正文");
mail1.setDate(new Date(0L));
CMailBefore mail2 = (CMailBefore) mail1.clone();
log.debug(Integer.toHexString(mail1.hashCode()) + " " + mail1);
log.debug(Integer.toHexString(mail2.hashCode()) + " " + mail2);
// 改变属性值
mail1.setName("更新");
mail1.getDate().setTime(999999999999L);
// 注意若使用mail1.setDate(new Date());方式赋值不会导致两者同时变更
log.debug("===============");
log.debug(Integer.toHexString(mail1.hashCode()) + " " + mail1);
log.debug(Integer.toHexString(mail2.hashCode()) + " " + mail2);
} }
/**
* output
* ===
* CMailAfter构造器调用
* 15d0c81b CMailAfter{name='原始', date=Thu Jan 01 08:00:00 CST 1970, content='原始正文'}
* 4b1c1ea0 CMailAfter{name='原始', date=Thu Jan 01 08:00:00 CST 1970, content='原始正文'}
* ===============
* 15d0c81b CMailAfter{name='更新', date=Sun Sep 09 09:46:39 CST 2001, content='原始正文'}
* 4b1c1ea0 CMailAfter{name='原始', date=Thu Jan 01 08:00:00 CST 1970, content='原始正文'}
* 耗时110ms
* ===
*
* @throws Exception
*/
@Test
void cloneTestAfter() throws Exception {
CMailAfter mail1 = new CMailAfter();
mail1.setName("原始");
mail1.setContent("原始正文");
mail1.setDate(new Date(0L));
CMailAfter mail2 = (CMailAfter) mail1.clone();
log.debug(Integer.toHexString(mail1.hashCode()) + " " + mail1);
log.debug(Integer.toHexString(mail2.hashCode()) + " " + mail2);
// 改变属性值
mail1.setName("更新");
mail1.getDate().setTime(999999999999L);
log.debug("===============");
log.debug(Integer.toHexString(mail1.hashCode()) + " " + mail1);
log.debug(Integer.toHexString(mail2.hashCode()) + " " + mail2);
}
} }