您的位置:首页 > 其它

设计模式(7):原型模式

2015-09-05 20:05 323 查看
原型模式的定义:

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

不通过new关键字来产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。

原型模式通用代码:

class PrototypeClass implements Cloneable {
	@Override
	protected PrototypeClass clone() throws CloneNotSupportedException {
		PrototypeClass prototypeClass = null;
		prototypeClass = (PrototypeClass) super.clone();
		return prototypeClass;
	}
}


实现Clonable接口,重写Clone方法,就完成了原型模式。

例子:

class AdvTemplate {
	// 广告信名称
	private String advSubject = "XX银行国庆信用卡抽奖活动";

	// 广告信内容
	private String advContxt = "国庆抽奖活动通知:只要刷卡就送你一百万!";

	public String getAdvSubject() {
		return this.advSubject;
	}

	public String getAdvContxt() {
		return advContxt;
	}
}

class Mail implements Cloneable {
	// 收件人
	private String receiver;
	// 邮件名称
	private String subject;
	// 称谓
	private String appellation;
	// 邮件内容
	private String contxt;
	// 邮件的尾部,一般都是加上“XX版权所有”等信息
	private String tail;

	public Mail(AdvTemplate advTemplate) {
		this.contxt = advTemplate.getAdvContxt();
		this.subject = advTemplate.getAdvSubject();
	}

	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 getContxt() {
		return contxt;
	}

	public void setContxt(String contxt) {
		this.contxt = contxt;
	}

	public String getTail() {
		return tail;
	}

	public void setTail(String tail) {
		this.tail = tail;
	}

	@Override
	protected Mail clone() {
		Mail mail = null;
		try {
			mail = (Mail) super.clone();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return mail;
	}

}

public class Client {
	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();
			mail.setAppellation(getReadingString(5) + "   先生  (女士) ");
			mail.setReceiver(getReadingString(5) + "@" + getReadingString(8)
					+ ".com");
			// 发送邮件
			sendMail(cloneMail);
			i++;
		}
	}

	private static void sendMail(Mail mail) {
		System.out.println("标题: " + mail.getSubject() + "\t 收件人 : "
				+ mail.getReceiver() + "\t 发送成功! ");
	}

	// 获得指定长度的字符串
	private static String getReadingString(int length) {
		String source = "qwertyuiopsdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
		StringBuffer sb = new StringBuffer();
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			sb.append(source.charAt(random.nextInt(source.length())));
		}
		return sb.toString();
	}
}


原型模式的优点:

性能优良

逃避构造函数的约束

原型模式的使用场景:

资源优化场景

性能和安全要求的场景

一个对象多个修改者的场景

原型模式注意事项:

1.构造函数不会执行

一个实现了Cloneable接口并重写了clone方法的类A,有一个无参构造或有参构造B,通过new关键字产生了一个对象S

再然后通过S.clone方式产生了一个对象T,那么在对象拷贝时构造函数B是不会被执行的。

2.浅拷贝和深拷贝

浅拷贝:

class Thing implements Cloneable {
	// 定义一个私有变量
	private ArrayList<String> arrayList = new ArrayList<String>();

	@Override
	protected Thing clone() throws CloneNotSupportedException {
		Thing thing = null;
		thing = (Thing) super.clone();
		return thing;
	}

	public void setValue(String value) {
		this.arrayList.add(value);
	}

	public ArrayList<String> getValue() {
		return this.arrayList;
	}
}

public class client {

	public static void main(String[] args) throws CloneNotSupportedException {
		Thing thing = new Thing();
		thing.setValue("张三");
		Thing cloneThing = thing.clone();
		cloneThing.setValue("李四");
		System.out.println(thing.getValue());
	}

}


Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝。

确实是非常浅,两个对象共享了一个私有变量,两个对象都可以对其进行改变,是一种非常不安全的方式。

但是对于String类型,Java就希望你把它认为是基本类型,它是没有clone方法的,处理机制也比较特殊,通过字符串池在需要的时候才在内存中

创建新的字符串。

使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:一是类的成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个

原始类型或不可便对象。

深拷贝:

class DeepThing implements Cloneable {
	private ArrayList<String> arrayList = new ArrayList<String>();

	@Override
	protected DeepThing clone() throws CloneNotSupportedException {
		
		DeepThing thing = null;
		thing = (DeepThing) super.clone();
		this.arrayList = (ArrayList<String>) this.arrayList.clone();
		return thing;
		
	}
	public void setValue(String value) {
		this.arrayList.add(value);
	}

	public ArrayList<String> getValue() {
		return this.arrayList;
	}
}

public class deepClient {
	public static void main(String[] args) throws Exception {

		DeepThing thing = new DeepThing();
		thing.setValue("张三");
		
		DeepThing cloneThing = thing.clone();
		cloneThing.setValue("李四");
		System.out.println(thing.getValue());
	}
}


只是比之前的例子多了

this.arrayList = (ArrayList<String>) this.arrayList.clone();

该方法就实现了完全的拷贝,两个对象之间没有任何的瓜葛了,互不影响,这就是深拷贝。

深拷贝还有一种实现方式时通过 自己写二进制流来操作对象,然后实现对象的拷贝。

clone和final是有冲突的

将ArrayList定义为final,编译器就会报错。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: