原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
Java 中有 Clone,因此这个原型模式用起来就很舒服。

我们先看一个案例,我们现在来模拟一个邮件的发送。
现在有一个邮件类:

1
2
3
4
5
public class Mail {
private String name;
private String emailAddress;
private String content;
}

里面的一些基本方法啥的被省略了。
再看一个工具类,这个工具类主要就是发送邮件的:

1
2
3
4
5
6
7
8
9
10
public class MailUtil {
public static void sendMail(Mail mail){
String output = "向{0}同学,邮件地址{1},邮件内容{2}" ;
System.out.println(MessageFormat.format(output , mail.getName() , mail.getEmailAddress(),mail.getContent()));
}

public static void save(Mail mail){
System.out.println("存储邮件记录: " + mail.getContent());
}
}

现在来看这个一般的邮件发送是怎么发送的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ProtoTypeTest {
public static void main(String[] args) {
Mail mail = new Mail();
mail.setContent("初始化模板");

for (int i = 0; i < 20; i++) {
mail.setName("姓名-" + i);
mail.setEmailAddress("name-"+ i + "@imooc.com");
mail.setContent("Content-: " + i);
MailUtil.sendMail(mail);
}
MailUtil.save(mail);
}
}

根据上面的呢,我们最后的结果一定不是我们所期待的结果,如果说我们将 mail 的构想构建放在 for 里面,那就会造成很多的 mail 的无用对像,浪费资源。这时候,原型模式就有了他的作用了。我们来看原型模式的一个修改.

我们需要修改的是, Mail 实现 Cloneable ,重写 clone 方法。

1
2
3
4
5
@Override
protected Object clone() throws CloneNotSupportedException {
System.out.println("clone mail");
return super.clone();
}

然后我们在主类中做修改:

1
2
3
4
5
6
7
8
for (int i = 0; i < 20; i++) {
Mail clone = (Mail) mail.clone();
clone.setName("姓名-" + i);
clone.setEmailAddress("name-"+ i + "@imooc.com");
clone.setContent("Content-: " + i);
MailUtil.sendMail(mail);
}
MailUtil.save(mail);

这样就好了。这就是最简单的原型了,这里的原型模式里面的克隆是由深克隆和浅克隆的,需要注意一下。