面向对象的编程中,创建一个对象是要开销资源的,比如java中通过new关键字来创建对象。但是有的时候,我们要创建大量的对象而这些对象的大部分属性都是相同只有部分属性会有变化。此时还使用new来创建对象,其开销的资源就比较大了,而且效率不高。于是我们就可以用到原型模式。
原型模式的定义是:通过编程语言(比如Java或C++)等提供的对象克隆(复制)方法来创建对象,而不是通过new关键字来创建对象。这种模式需要先有一个相当于对象模板的类,然后通过克隆的方式快速生成和原型具有相同或者相似属性的新对象。
原型模式的UML类图如下:

在这个模式中,其核心结构:
- 首先定义一个克隆方法的接口,所有具体的原型都实现这个接口
- 然后创建一个具体的原型类,实现这个接口并提供一个
clone方法,让它能够复制自身
- 最后,在调用的时候通过原型对象的
clone方法来创建新对象。
举一个具体的例子,比如我们的系统中要提供一个邮件订阅的功能,当我们向订阅者发送邮件的时候,邮件内容基本是相同的,每一封邮件的区别可能只是收件人地址或者称呼有区别,那么我们就可以通过原型模式来快速创建邮件对象。
下面是实例代码,在这个例子中我们假设给两类用户发邮件,一类用来通知订单发货、一类用来通知用户的积分情况。
首先创建一个邮件对象接口
1 2 3 4 5 6 7 8 9
| package protyotype;
public interface Email extends Cloneable { Email clone(); void setRecipient(String recipient); void setContent(String content); void send(); }
|
然后在具体的通知邮件对象中实现克隆方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package protyotype;
public class NotificationEmail implements Email { private String subject = "[系统通知] "; private String recipient; private String content; private String footer = "\n\n---\n系统自动发送,请勿回复";
@Override public Email clone() { try { return (NotificationEmail) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("克隆失败", e); } }
@Override public void setRecipient(String recipient) { this.recipient = recipient; }
@Override public void setContent(String content) { this.content = content; }
@Override public void send() { System.out.println("发送邮件至:" + recipient); System.out.println("主题:" + subject); System.out.println("内容:" + content + footer); System.out.println("-------------------"); } }
|
最后在客户端中调用,使用clone方法来创建对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package protyotype;
public class EmailClient { public static void main(String[] args) { Email template = new NotificationEmail(); Email email1 = template.clone(); email1.setRecipient("user1@example.com"); email1.setContent("您的订单已发货,物流单号:12345"); email1.send(); Email email2 = template.clone(); email2.setRecipient("user2@example.com"); email2.setContent("您的会员积分已到账,当前积分:500"); email2.send(); } }
|
总之,原型模式在应对批量创建相似属性对象时具有优势,而且灵活性更高,其使用编程语言内置的克隆方法也更加节省资源开销,在一些诸如邮件通知、消息推送或者报表生成等场景中较为常用。