文章目录
- 1. 原型模式
-
- 1.1 定义
- 1.2 使用场景
- 1.3 模拟代码
- 1.4 浅克隆和深克隆
- 1.5 原型模式破坏单例
- 1.6 应用源码解析
1. 原型模式
1.1 定义
- 指原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。不需要知道任何创建的细节,不需要构造函数。
- 该设计模式主要有四个组件(抽象Builder,实体Builder,产品,Director)。
1.2 使用场景
- 类初始化消耗较多资源。
- new产生的对象需要非常繁琐的过程。
- 构造函数比较复杂。
- 在循环体中产生大量对象时。
1.3 模拟代码
- 以循环发送邮件为例,由于new出一个新邮件的代价是非常高的,所以采用clone方式进行创建新的Mail对象,采用克隆方式是不会调用类的构造器的。重点是要实现Cloneable接口,并重写Object的clone方法。
- Mail类
package com.fukexin.design.pattern.creational.prototype;
public class Mail implements Cloneable{
private String emailName;
private String emailAddress;
private String emailContent;
public Mail()
{
System.out.println("Mail Class Constructor");
}
public String getEmailName() {
return emailName;
}
public void setEmailName(String emailName) {
this.emailName = emailName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getEmailContent() {
return emailContent;
}
public void setEmailContent(String emailContent) {
this.emailContent = emailContent;
}
@Override
public String toString() {
return "Mail{" +
"emailName='" + emailName + '\'' +
", emailAddress='" + emailAddress + '\'' +
", emailContent='" + emailContent + '\'' +
'}'+super.toString();
}
@Override
protected Object clone() throws CloneNotSupportedException {
System.out.println("clone mail object");
return super.clone();
}
}
}
- MailUtil类
package com.fukexin.design.pattern.creational.prototype;
import java.text.MessageFormat;
public class MailUtil {
public static void sendMail(Mail mail)
{
String outputContent = "向{0}同学,邮件地址:{1},邮件内容:{2},发送邮件成功";
System.out.println(MessageFormat.format(outputContent,mail.getEmailName(),mail.getEmailAddress(),mail.getEmailContent()));
}
public static void saveOriginMailRecord(Mail mail)
{
System.out.println("存储originMail记录:"+mail.getEmailContent());
}
}
- Test类
package com.fukexin.design.pattern.creational.prototype;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Mail mail=new Mail();
mail.setEmailContent("初始化模板");
for(int i=0;i<10;i++){
Mail mailTemp= (Mail) mail.clone();
mailTemp.setEmailName("同学"+i);
mailTemp.setEmailAddress("同学"+i+"@jnu.com");
mailTemp.setEmailContent("恭喜你被退学啦!");
MailUtil.sendMail(mailTemp);
}
MailUtil.saveOriginMailRecord(mail);
}
}
1.4 浅克隆和深克隆
- 浅克隆:A对象中属性有值类型(int,double等等),也有引用类型,B对象是由A对象浅克隆的出来的对象(只重写clone方法,不进行其他修改),这是B对象中引用类性的引用与A对象中的引用类型的引用相同,当修改A对象引用类型的值时,B对象同样也会被修改。
- 深克隆:A对象中属性有值类型(int,double等等),也有引用类型,B对象是由A对象深克隆的出来的对象(重写clone方法后,要对引用类型一一进行克隆),这是B对象中引用类性的引用与A对象中的引用类型的引用不同,当修改A对象引用类型的值时,B对象不会被修改。
1.5 原型模式破坏单例
- 学完单例再来写!
1.6 应用源码解析
-
java.util.ArrayList实现了Cloneable接口,重写了clone方法,使用Arrays.copyOf
将数组中的元素拷贝到克隆对象。
public Object clone() {
try {
ArrayList<?> v = (ArrayList)super.clone();
v.elementData = Arrays.copyOf(this.elementData, this.size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException var2) {
throw new InternalError(var2);
}
}
- java.util.HashMap实现了Cloneable接口,重写了clone方法。
@HotSpotIntrinsicCandidate
public Object clone() {
HashMap result;
try {
result = (HashMap)super.clone();
} catch (CloneNotSupportedException var3) {
throw new InternalError(var3);
}
result.reinitialize();
result.putMapEntries(this, false);
return result;
}
- Mybatis中的CacheKey实现了Cloneable接口,重写了clone方法。(关于List的克隆,主要看里面的内容是什么,里面的是值类型,就会克隆一份新的。里面的是引用类型,就是同一个)。
public CacheKey clone() throws CloneNotSupportedException {
CacheKey clonedCacheKey = (CacheKey)super.clone();
clonedCacheKey.updateList = new ArrayList(this.updateList);
return clonedCacheKey;
}