4、PROTOTYPE(原型)
2019-05-19 本文已影响0人
我要扭开奥利奥
目的
用原型实列指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
使用场景
当一个系统应该独立于他的产品创建、构成和表示时,要使用Prototype模式;另外:
- 当要实例化的类实在运行时指定的时候,例如动态装载
- 为了避免创建一个与产品层次平行的工厂类层次时
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆他们可能比每次用合适的状态手工实例化该类更方便一些。
具体描述
我们假设一个场景:小明是一名文员,每天的工作是发邮件,每天他都要发送数以万计的邮件,但是其实他们的邮件内容是大同小异的,所以他想把他们的邮件系统增加一个模板功能。在创建一个模板后能够使用克隆方法来创建新邮件,新邮件就只需要小的修改就能够发送。小陈是他们的邮件系统开发人员,小陈看了需求之后决定使用** 原型模式 ** 来开发这个功能。
image.png
其中,邮件模板是Prototype,其定义了clone()方法,ConcretePrototype是其实现类,他实现了clone()方法,将会返回他的拷贝。在拷贝的时候,将会有两个选择,一个是浅拷贝,一个是深拷贝。他们之间的区别主要是浅拷贝在拷贝引用对象的时候只拷贝其引用,也就是拷贝出来的所有对象和原型的指针指向的对象都是同一个对象,内存区域都是相同的;然然深拷贝是拷贝对象的实例而不是引用,每一个对象都拥有自己独立的对象。在这个例子中小陈觉得因为小明的工作量较大,需要使用多线程发送邮件,如果使用浅拷贝那么可鞥会出现不可预知的问题,因此他决定使用深拷贝来确保安全性。同时,小陈是一名Java开发人员,在Java里面其基类Object类是含有Clone方法的,如果要实现Clone方法只需要继承Cloneable就可以了。其具体实现如下:
原型类:MailProtopyte
public class MailPrototype {
String context = "欢迎来到本公司参观";
}
实现类:Mail
package prototype;
import java.util.ArrayList;
import java.util.List;
public class Mail implements Cloneable{
String name;
String address;
String context;
ArrayList<String> visitDepartment = new ArrayList<>();
public Mail(MailPrototype mailPrototype){
this.context = mailPrototype.context;
//每个人都需要参观人事部门
visitDepartment.add("人事部门");
}
@Override
public String toString() {
return "Mail{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", context='" + context + '\'' +
", visitDepatment=" + visitDepartment.toString() + '\''+
'}';
}
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
public void addVisitDepartment(String item){
visitDepartment.add(item);
}
public Mail clone(){
Mail mail = null;
try{
mail = (Mail)super.clone();
//深拷贝引用对象visitDepartment
mail.visitDepartment = (ArrayList<String>) this.visitDepartment.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return mail;
}
}
测试类:Client
package prototype;
import java.util.ArrayList;
import java.util.List;
public class Client {
public static void main(String[] args){
Mail prototypeMail = new Mail(new MailPrototype());
Mail mail1 = prototypeMail.clone();
Mail mail2 = prototypeMail.clone();
mail1.setName("1");
mail1.setAddress("1");
//第一个人需要参观安全部门,第二个人不需要参观安全部门
mail1.addVisitDepartment("安全部门");
System.out.println(mail1.toString());
mail2.setName("2");
mail2.setAddress("2");
System.out.println(mail2.toString());
}
}
输出结果如下:
Mail{name='1', address='1', context='欢迎来到本公司参观', visitDepatment=[人事部门, 安全部门]'}
Mail{name='2', address='2', context='欢迎来到本公司参观', visitDepatment=[人事部门]'}