1 原型模式定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
Prototype 模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
2 如何使用?
因为 Java 中的提供 clone()方法来实现对象的克隆,所以 Prototype 模式实现一下子变得很简单。
package xx.study.design.prototype;
public class Spoon implements Cloneable{
String spoonName;
public void setSpoonName(String spoonName) {
this.spoonName =spoonName;
}
public String getSpoonName() {
return this.spoonName;
}
public Spoon(String spoonName){
this.spoonName=spoonName;
}
public Object clone()
{
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractSpoon is not Cloneable");
}
return object;
}
}
package xx.study.design.prototype;
public class PorotypeDemo {
public static void main(String[] args) {
Spoon spoon = new Spoon("大勺子");
System.out.println(spoon.getSpoonName());
Spoon spoon2 = (Spoon) spoon.clone();
System.out.println(spoon2.getSpoonName());
}
}
3 clone拓展
3.1 浅拷贝和深拷贝
浅拷贝:被复制对象的所有值属性都含有与原来对象的相同,而所有的对象引用属性仍然指向原来的对象。(上述案例修改一个对象,会把另外一个对象也会修改)
深拷贝:在浅拷贝的基础上,所有引用其他对象的变量也进行了clone,并指向被复制过的新对象。
也就是说,一个默认的clone()方法实现机制,仍然是赋值。
如果一个被复制的属性都是基本类型,那么只需要实现当前类的cloneable机制就可以了,此为浅拷贝。
如果被复制对象的属性包含其他实体类对象引用,那么这些实体类对象都需要实现cloneable接口并覆盖clone()方法。
3.2 深拷贝实现
package xx.study.design.prototype;
public class SpoonExtend implements Cloneable{
String spoonName;
public void setSpoonName(String spoonName) {
this.spoonName =spoonName;
}
public String getSpoonName() {
return this.spoonName;
}
public SpoonExtend(String spoonName){
this.spoonName=spoonName;
}
public Object clone()
{
Object object = null;
try {
object = super.clone();
String sn=((SpoonExtend)object).getSpoonName();
//需要显式地clone其引用成员;如果是类变量 此类实现
//Cloneable,setSpoonName(sn.clone())
((SpoonExtend)object).setSpoonName(sn+"");
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractSpoon is not Cloneable");
}
return object;
}
}
package xx.study.design.prototype;
public class PorotypeDemo {
public static void main(String[] args) {
Spoon spoon = new Spoon("大勺子");
System.out.println(spoon.getSpoonName());
Spoon spoon2 = (Spoon) spoon.clone();
System.out.println(spoon2.getSpoonName());
spoon.setSpoonName("小勺子");
System.out.println(spoon.getSpoonName());
System.out.println(spoon2.getSpoonName());
System.out.println("测试2");
SpoonExtend se = new SpoonExtend("大勺子");
SpoonExtend se2 = (SpoonExtend) se.clone();
System.out.println(se.getSpoonName());
System.out.println(se2.getSpoonName());
se2.setSpoonName("我变了,你变了,吗");
System.out.println(se2.getSpoonName());
System.out.println(se.getSpoonName());
}
}
一句话来说,如果实现完整的深拷贝,需要被复制对象的继承链、引用链上的每一个对象都实现克隆机制。
前面的实例还可以接受,如果有N个对象成员,有M层继承关系,就会很麻烦。
3.3 使用Orika深拷贝
此方式虽然不比原生clone效率高,与其他相比相比效率较高。其他实现可以参考
https://blog.csdn.net/54powerman/article/details/64920431?locationNum=6&fps=1
1依赖
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.0</version>
</dependency>
package xx.study.design.prototype;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
public class OrikaClone {
public static void main(String[] args) {
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Spoon.class,Spoon.class).byDefault().register();
ConverterFactory converterFactory = mapperFactory.getConverterFactory();
MapperFacade mapper = mapperFactory.getMapperFacade();
Spoon s1=new Spoon("勺子");
Spoon s2 = mapper.map(s1, Spoon.class);
System.out.println(s1.getSpoonName());
System.out.println(s2.getSpoonName());
s2.setSpoonName("小勺");
System.out.println(s1.getSpoonName());
System.out.println(s2.getSpoonName());
}
}