Prototype Patttern
specify the kinds of objects to create using a prototypical instance,and create new objects by coping this prototype.(用原型实例实例指定创建对象的种类,并且通过拷贝这个原型创建新的对象)
实现Clonable接口,实现clone方法即可。
例子
发邮件
public class AdvTemplate {
private String advSubject = "XX银行抽奖活动"; //广告名称
private String advContext = "只要刷卡就就送你10Q币"; //广告内容
public String getAdvSubject() {
return advSubject;
}
public String getAdvContext() {
return advContext;
}
}
public class Mail implements Cloneable{
private String receiver;
private String subject;
private String appellation;
private String context;
private String tail;
public Mail(AdvTemplate advTemplate){
this.context=advTemplate.getAdvContext();
this.subject=advTemplate.getAdvSubject();
}
@Override
protected Mail clone(){
Mail mail=null;
try {
mail=(Mail) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return mail;
}
public String getReceiver() {
return receiver;
}
public void setReceiver(String receiver) {
this.receiver = receiver;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getAppellation() {
return appellation;
}
public void setAppellation(String appellation) {
this.appellation = appellation;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public String getTail() {
return tail;
}
public void setTail(String tail) {
this.tail = tail;
}
}
public class ClientI {
private static int MAX_COUNT=6;
public static void main(String[] args) {
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++;
}
}
private static void sendMail(Mail mail) {
System.out.println("标题:"+mail.getSubject()+"\t 收件人:"+mail.getReceiver()+"发送成功!");
}
private static String getRandString(int maxLength){
String source="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringBuffer sb=new StringBuffer();
Random random=new Random();
for(int i=0;i<maxLength;i++){
sb.append(source.charAt(random.nextInt(source.length())));
}
return sb.toString();
}
}
特点
1.克隆时构造函数不会执行
2.Object中的clone()方法为浅拷贝,只拷贝对象本身,其内部的数组,引用对象等不拷贝,还是指向原生对象的内部元素地址。 俩个对象共享一个私有变量,不安全。
public class Thing implements Cloneable{
private ArrayList<String> list=new ArrayList<String>();
public Thing(){
System.out.println("执行了构造方法");
}
/*浅拷贝:俩个对象共享了一个私有变量,指向原生对象的内部元素地址,不安全
*深拷贝:thing.list=(ArrayList<String>) this.list.clone();
*满足俩个条件时才不会被拷贝:1.类的成员变量 2.必须是一个可变的引用对象,而不是一个原始类型或不可变对象
*/
@Override
protected Thing clone(){
Thing thing=null;
try {
thing=(Thing) super.clone();
thing.list=(ArrayList<String>) this.list.clone();
//没有这句的结果不一样
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return thing;
}
public void setValue(String value){
list.add(value);
}
public ArrayList<String> getValue(){
return this.list;
}
}
public static void main(String[] args) {
Thing thing=new Thing();
thing.setValue("LOL");
Thing thingClone=thing.clone();
thingClone.setValue("CF");
System.out.println(thing.getValue());
}
}
结果:不管是浅拷贝还是深拷贝,构造函数只执行一次,浅拷贝会改变原来的集合值,而深拷贝不会,俩个独立。
性能优良
内存二进制流的拷贝,比new性能好很多,特别是需要产生大量对象时
逃避构造函数的约束,构造函数=约束
使用场景
产生一个对象需要非常繁琐的数据准备或访问权限时,可以使用
缺点使用,当一个对象需要多个对象访问时,而且各个调用者可以修改其值时(不得不说,任何事物不能看的太窄了,缺点即优点)
悟:从内存中复制对象,分为浅复制和深复制。不安全,要看使用场合。
我是菜鸟,我在路上。