1、原型模式
原型模式是指将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的对象。原型模式是一种创建型模式。
原型模式的工作原理很简单:将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程。原型模式是一种“另类”的创建型模式,创建克隆对象的工厂就是原型类自身,工厂方法由克隆方法来实现。
组成:
1)
Prototype
(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。
2)
ConcretePrototype
(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
类图:
通用的克隆方法是在具体原型实现类中实例化(克隆)一个与自身类型相同的对象并将其返回;
代码:
abstract class Prototype{
public Prototype clone(){
return null;
}
}
class ConcretePrototype extends Prototype{
private String sttr ;
public String getSttr() {
return sttr;
}
public void setSttr(String sttr) {
this.sttr = sttr;
}
public Prototype clone(){
ConcretePrototype prototyoe = new ConcretePrototype();
prototyoe.setSttr(this.sttr);
return prototyoe;
}
}
适用场景:创建对象成本较大,如初始化占用较长时间、占用大量cpu资源等,新的对象可以通过原型对象复制产生新的对象。
总结 :
使用原型模式在创建新的较复杂对象时,使用原型可以简化对象创建过程,通过复制提高效率。但是
每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”。
2、JDK中原型模式应用
在jdk中,Prototype原型抽象类对应Cloneable接口,一个原型类,只需要实现 Cloneable 接口,覆写 clone 方法,此处 clone 方法可以改成任意的
名称,因为 Cloneable 接口是个空接口,你可以任意定义实现类的方法名,如 cloneA 或者 cloneB,因
为此处的重点是 super.clone()这句话, super.clone()调用的是 Object 的 clone()方法,而在 Object 类中。
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指
向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深
复制进行了完全彻底的复制,而浅复制不彻底。
浅复制实例:
class ShallowClone implements Cloneable{
String name = "xl" ;
int age = 20 ;
@Override
protected ShallowClone clone() {
// TODO Auto-generated method stub
Object object = null ;
try{
object = super.clone();
return (ShallowClone)object;
}catch(CloneNotSupportedException EX){
System.out.println("NOT SUPPORT CLONE !!");
return null ;
}
}
}
深复制实例:
class DeepClone implements Cloneable{
String name = "xl" ;
int age = 20 ;
protected DeepClone deepClone() throws CloneNotSupportedException,IOException, ClassNotFoundException{
/* 写入当前对象的二进制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 读出二进制流产生的新对象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (DeepClone)ois.readObject();
}
}