梦想还是要有的,万一忘了咋办?

0%

原型模式

概述

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

类图

upload successful

角色

  • 客户(Client)角色
  • 抽象原型(Prototype)角色
  • 具体原型 (Concrete Prototype)角色

Java中内置了克隆机制,Object类具有一个clone()方法,能够实现对象的克隆,使一个类支持克隆需要以下两步:

  • 实现Cloneable 接口
  • 覆盖 Object的clone方法,完成对象的克隆操作,通常只需要调用Object的clone方法即可。为了使外部能够调用此类的clone方法,可以将可访问属性修改为public

示例

Prototype.java

1
2
3
public interface Prototype extends Cloneable{
Prototype clone();
}

ConcretePrototypel.java

1
2
3
4
5
6
7
8
9
10
public class ConcretePrototype implements Prototype{

public Prototype clone(){
try{
return (Prototype)super.clone();
}catch(CloneNotSuppoertedException e){
return null;
}
}
}

Client.java

1
2
3
4
5
public class Client{
public void operation(Prototype example){
Prototype p=example.clone();
}
}

应用

优点

  • 性能优良
  • 逃避构造函数的约束

使用场景

  • 资源优化场景,类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  • 性能和安全要求的场景,通过new产生一个对象需要非常繁琐的数据准备或者访问权限,可以通过原型模式。
  • 一个对象多个修改者的场景,一个对象需要提供给其它对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式复制多个对象供调用者使用。

在实际项目中,原型模式很少独立出现,一般和工厂方法模式一起出现,通过clone方法创建一个对象,然后由工厂方法提供给调用者。

实例

Mail.java

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
public class Mail implements Cloneable{
//收件人
private String receiver;
   //邮件标题
private String subject;
   //称谓
private String appellation;
   //邮件内容
private String context;
   //邮件尾巴
private String tail;

public Mail(String subject,String context){
this.subject=subject;
this.context=context;
}

public Mail clone(){
Mail mail=null;
try{
mail=(Mail)super.clone();
}catch(CloneNotSupportedException e){
return null;
}
}
}

ClientDemo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ClientDemo{
private static int MAX_CONT=6;
public static void main(String[] args){
int i=0;
       Mail mail=new Mail("主题","内容");
       mail.setTail("版权所有");
       while(i<MAX_CONT){
Mail cloneMail=mail.clone();
           cloneMail.setAppellation(i+"先生/女士");
cloneMail.setReceiver(i+"_email@111.com");
           sendMail(cloneMail)
}
   }

public static void sendMail(Mail mail){
System.out.println("send mail to "+mail.getAppellation()+" ,"+mail.getSubject())
}

}