原型模式
2017-04-24 本文已影响49人
程序员丶星霖
原型模式
定义
原型模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。
英文定义:Specify the kinds of objects to create using a prototypical instance , and create new objects by copying this prototype .(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)
原型模式的UML类图如下所示
原型模式.jpg上图中主要涉及一下角色:
- 客户端(Client):客户端提出创建对象的请求。
- 抽象原型(Prototype):通常由一个Java接口或者Java抽象类来实现,从而为具体原型设立好规范。
- 具体原型(ConcretePrototype):被复制的具体对象,这个具体角色实现了抽象原型角色所要求实现的方法。
原型模式的通用代码如下:
//原型模式通用源码
public class PrototypeClass implements Cloneable{
//覆写父类Object方法
@Override
public PrototypeClass clone(){
PrototypeClass prototypeClass = null;
try{
prototypeClass = (PrototypeClass)super.clone();
}catch(CloneNotSupportedExecption e){
//异常处理
}
return prototypeClass;
}
}
优缺点
优点:
- 性能优良:原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多。
- 逃避构造函数的约束:直接在内存中拷贝,构造函数是不会执行的。
- 提供简化的创建结构。
- 具有给一个应用软件动态加载新功能的能力。
缺点:
- 每一个类都必须配备一个复制方法,对于全新的类来说不是很难,而对已有的类来说实现clone()方法不一定很容易,而且在进行比较深层次的复制时也需要编写一定量的代码。
应用场景:
- 资源优化:类初始化需要消化非常多的资源。
- 性能和安全要求:通过new产生一个对象需要非常繁琐的数据准备或访问权限,可以使用原型模式。
- 一个对象多个修改者:一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
- 隐藏复制操作的细节
注意事项
1.构造函数不会被执行
一个实现了Cloneable并重写了clone方法的类,在对象拷贝时构造函数是不会被执行的。
代码如下所示:
public class Thing implements Cloneable{
public Thing(){
System.out.println("构造函数被执行了......");
}
@Override
public Thing clone(){
Thing thing = null;
try{
thing = (Thing)super.clone();
}catch(CloneNotSupportedExecption e){
e.printStackTrace();
}
return thing;
}
}
public class Client{
public static void main(String[] args){
//产生一个对象
Thing thing = new Thing();
//拷贝一个对象
Thing cloneThing = thing.clone();
}
}
2.浅拷贝和深拷贝
浅拷贝:Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址。浅拷贝是对基本数据类型和String类型而言的。
//浅拷贝
public class Thing implements Cloneable{
//定义一个私有变量
private ArrayList<String> arrayList = new ArrayList<String>();
@Override
public Thing clone(){
Thing thing = null;
try{
thing = (Thing)super.clone();
}catch(CloneNotSupportedExecption e){
e.printStackTrace();
}
return thing;
}
//设置HashMap的值
public void setValue(String value){
this.arrayList.add(value);
}
//取得ArrayList的值
public ArrayList<String> getValue(){
return this.arrayList;
}
}
//浅拷贝测试
public class Client{
public static void main(String[] args){
//产生一个对象
Thing thing = new Thing();
//设置一个值
thing.setValue("张三");
//拷贝一个对象
Thing cloneThing = thing.clone();
cloneThing.setValue("李四");
System.out.println(thing.getValue());
}
}
深拷贝:实现完全的拷贝,两个对象之间没有任何的瓜葛。深拷贝是对其他引用类型而言的。
代码如下所示:
//深拷贝
public class Thing implements Cloneable{
//定义一个私有变量
private ArrayList<String> arrayList = new ArrayList<String>();
@Override
public Thing clone(){
Thing thing = null;
try{
thing = (Thing)super.clone();
this.arrayList = (ArrayList<String>)this.arrayList.clone();
}catch(CloneNotSupportedExecption e){
e.printStackTrace();
}
return thing;
}
}
注意:
使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:
- 类是成员变量,而不是方法内变量;
- 必须是一个可变的引用对象,而不是一个原始类型或不可变对象。
3.clone与final
- 要使用clone方法,类的成员变量上不要增加final关键字。