设计模式之原型模式

设计模式之原型模式

1. 什么是原型模式

Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。

换句话说原型模式就是通过复制现有实例来创建新的实例,无须知道相应类的信息。

原型模式的结构:
在这里插入图片描述

优缺点

优点:

  • 使用原型模式创建对象比直接new一个对象更有效,因为他是直接对内存进行拷贝,数据对象的内容就全部都有了,不需要重新创建内存区域重新实例化赋值这些操作了,这样的话速度能够快很多。

  • 隐藏制造新实例的复杂性

  • 重复地创建相似对象时可以考虑使用原型模式

缺点:

  • 每一个类必须配备一个克隆方法
  • 深层复制比较复杂

特点:

  • 由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。

  • 目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。

  • 根据对象克隆深度层次的不同,有浅度克隆与深度克隆。

适用场合:

  • 复制对象的结构与数据

  • 希望对目标对象的修改不影响既有的原型对象

  • 创建对象成本较大的情况下

  • 在创建对象的时候,我们不只是希望被创建的对象继承其基类的基本结构,还希望继承原型对象的数据。

  • 希望对目标对象的修改不影响既有的原型对象(深度克隆的时候可以完全互不影响)

  • 隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。

使用时注意事项:

  • 使用原型模式复制对象不会调用类的构造方法。所以,单例模式与原型模式是冲突的,在使用时要特别注意。

  • Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。

2. 具体实例:

银行的电子账单、广告信需要你群发邮件,特点:量大、时间要求紧。

想一下这个怎么实现,其实简单的想法就是邮件类,邮件模板类,发送邮件类这样三个函数,然后使用多线程给每个线程分配一个邮件的对象进行发送。这样的话的缺点就是需要实例化很多的对象,实例化对象的时候会有类的初始化赋值这一类的操作,速度慢,然后我们想就是因为每一封邮件是类似的,只是发送的人姓名什么的不同,我们直接拷贝对象,直接从内存中拷贝对象的话对象的信息都有然后重新进行修改,省下了new的整个过程,速度快很多。

设计的类图:

在这里插入图片描述

其实从图中看不出具体的原型模式是怎么回事。看一下具体的代码;

public class EventTemplate {
	private String eventSubject, eventContent;

	public EventTemplate(String eventSubject, String eventContent) {
		this.eventSubject = eventSubject;
		this.eventContent = eventContent;
	}

	public String geteventSubject() {
		return eventSubject;
	}

	public String geteventContent() {
		return eventContent;
	}
}
public class Mail implements Cloneable {
	private String receiver;
	private String subject;
	private String content;
	private String tail;
	private ArrayList<String> ars;
	public Mail(EventTemplate et) {
		this.tail = et.geteventContent();
		this.subject = et.geteventSubject();
	
	}

	@Override
	public Mail clone() {
		Mail mail = null;
		try {
			mail = (Mail) super.clone();
			mail.ars = (ArrayList<String>)this.ars.clone();
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			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 void setContent(String content) {
		this.content = content;
	}

	public String getContent() {
		return content;
	}

	public String getTail() {
		return tail;
	}

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

Mail这个类实现了Cloneable,继承了public Mail clone() {}这个方法,用来实现对象的拷贝。

public class MainTest {
	public static void main(String[] args) {
		int i = 0;
		int MAX_COUNT = 10;
		EventTemplate et = new EventTemplate("9月份信用卡账单", "国庆抽奖活动...");

		Mail mail = new Mail(et);

		while (i < MAX_COUNT) {
			// 以下是每封邮件不同的地方
			Mail cloneMail = mail.clone();
			cloneMail.setContent(getRandString(5) + ",先生(女士):你的信用卡账单..."
					+ mail.getTail());
			cloneMail.setReceiver(getRandString(5) + "@" + getRandString(8)
					+ ".com");
			// 然后发送邮件
			sendMail(cloneMail);
			i++;
		}

	}

	public static 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();
	}

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

在测试类中每次发不同的邮件时都会Mail cloneMail = mail.clone();就是对象的复制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值