package com.cheng.zenofdesignpatterns.patterns.prototype;
import android.view.View;
import com.cheng.zenofdesignpatterns.ZoDPChapterBaseActivity;
import com.cheng.zenofdesignpatterns.patterns.prototype.notes.DeepCopy;
import com.cheng.zenofdesignpatterns.patterns.prototype.notes.ShallowCopy;
import com.cheng.zenofdesignpatterns.patterns.prototype.notes.Thing;
import com.cheng.zenofdesignpatterns.patterns.prototype.sendmail.AdvTemplate;
import com.cheng.zenofdesignpatterns.patterns.prototype.sendmail.Mail;
import java.util.Random;
public class ZoDPPrototypeActivity extends ZoDPChapterBaseActivity {
@Override
protected void initData() {
mTitleTV.setText("原型模式");
String content = "定义:\n" +
"Specify the kinds of objects to create using a prototypical instance," +
"and create new objects by copying this prototype.\n" +
"用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。\n\n" +
"原型模式的优点\n" +
"- 性能优良\n" +
"原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循" +
"环体内产生大量的对象时,原型模式可以更好地体现其优点。\n" +
"- 逃避构造函数的约束\n" +
"这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。\n\n" +
"使用场景\n" +
"- 资源优化场景\n" +
"类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等。\n" +
"- 性能和安全要求的场景\n" +
"通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。\n" +
"- 一个对象多个修改者的场景\n" +
"一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以" +
"考虑使用原型模式拷贝多个对象供调用者使用。\n\n" +
"注意事项\n" +
"1. 构造函数不会被执行\n" +
"2. 浅拷贝和深拷贝\n" +
"注意 使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:一是类的" +
"成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个原始类" +
"型或不可变对象。\n" +
"注意 深拷贝和浅拷贝建议不要混合使用,特别是在涉及类的继承时,父类有多个引用" +
"的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。\n" +
"3. clone和final两个冤家\n" +
"对象的clone和对象内的final关键字是有冲突的。\n" +
"注意 要使用clone方法,类的成员变量上不要增加final关键字。\n\n" +
"最佳实践\n" +
"原型模式先产生出一个包含大量共有信息的类,然后可以拷贝出副本,修正细节信息," +
"建立了一个完整的个性对象。可以这样理解:一个对象的产生可以不由零起步,直接从" +
"一个已经具备一定雏形的对象克隆,然后再修改为生产需要的对象。";
mContentTV.setText(content);
}
@Override
public void onClick(View v) {
// 1. 批量发送邮件
// 发送账单的数量,这个值是从数据库中获得
final int MAX_COUNT = 6;
// 模拟发送邮件
int i=0;
// 把模板定义出来,这个是从数据中获得
Mail mail = new Mail(new AdvTemplate());
mail.setTail("XX银行版权所有");
while(i<MAX_COUNT){
// 以下是每封邮件不同的地方
Mail cloneMail = mail.clone();
cloneMail.setAppellation(getRandString(5)+" 先生(女士)");
cloneMail.setReceiver(getRandString(5) + "@" + getRandString(8)+".com");
// 然后发送邮件
sendMail(cloneMail);
i++;
}
// 2. 构造函数不会被执行
// 产生一个对象
Thing thing = new Thing();
// 拷贝一个对象
Thing cloneThing = thing.clone();
// 3. 浅拷贝
// 产生一个对象
ShallowCopy shallowCopy = new ShallowCopy();
// 设置一个值
shallowCopy.setValue("张三");
// 拷贝一个对象
ShallowCopy cloneShallowCopy = shallowCopy.clone();
cloneShallowCopy.setValue("李四");
System.out.println(shallowCopy.getValue());
// 4. 深拷贝
// 产生一个对象
DeepCopy deepCopy = new DeepCopy();
// 设置一个值
deepCopy.setValue("张三");
deepCopy.setValue("abcd");
// 拷贝一个对象
DeepCopy cloneDeepCopy = deepCopy.clone();
cloneDeepCopy.setValue("李四");
System.out.println(deepCopy.getValue());
}
//发送邮件
private void sendMail(Mail mail){
System.out.println("标题:"+mail.getSubject() + "\t收件人:"+mail.getReceiver()+"\t....发送成功!");
}
//获得指定长度的随机字符串
private String getRandString(int maxLength){
String source ="abcdefghijklmnopqrskuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuffer sb = new StringBuffer();
Random rand = new Random();
for(int i=0;i<maxLength;i++){
sb.append(source.charAt(rand.nextInt(source.length())));
}
return sb.toString();
}
}