原型模式
原型模式是23种设计模式之一,和单例模式一样,相对其他设计模式较为容易理解。
定义
原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。[1]
原型模式通过克隆一个已经存在的对象实例来返回新的实例,而不是通过new去创建对象,多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效。在Java中,复制对象是通过原型对象实现Cloneable接口,重写clone()方法实现的
在实际开发中我们也经常使用克隆方法,下面是我在工作中遇到的案例,业务非常的简单
业务需求:
要求对数据的update,modify,delete的操作,都需要备份原始数据,提高业务的容错性
解决方案:
操作数据前先根据主键或唯一字段查出数据,再用BeanUtils.copyProperties(source, target)方法克隆出一个新的类
注:这里我们调用了BeanUtils中的copyProperties(source, target)方法来进行数据的复制。当然你也可以使用原始的get和set的方法进行数据的复制,但是当类中的字段相当庞大时,原始的办法就显得相当的繁琐。
//修改数据源信息
@Transactional
public void modifyDbConf(TMdDbConfig dbConfig) {
//根据confName查询旧数据
String confName = dbConfig.getConfName();
TMdDbConfig olDbConfig = tmdDbConfigMapper.selectByPrimaryKey(confName);
TMdDbConfigLog dbLog = new TMdDbConfigLog();
//封装数据
BeanUtils.copyProperties(olDbConfig, dbLog);
dbLog.setOperator(dbConfig.getModifier());
dbLog.setOperationTime(dbConfig.getModifyTime());
tmdDbConfigMapper.saveDbLog(dbLog);
tmdDbConfigMapper.modifyDbConf(dbConfig);
}
下面我们来讲讲原型模式的简单实现
对象的克隆分为2种:浅可怜和深度克隆
/**
* @description:浅克隆(浅复制)
*/
public class ShallowClone implements Cloneable,Serializable{
private String name;
private int age;
List<String> hobbies = new ArrayList<>();
public List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* 重写clone方法
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object clone = null;
try {
clone = super.clone();
}catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
浅克隆:
创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
测试代码
public static void main(String[] args) {
ShallowClone shallowClone = new ShallowClone();
shallowClone.setName("Tom");
shallowClone.setAge(18);
shallowClone.setHobbies(new ArrayList<>());
ShallowClone clone = null;
try {
clone = (ShallowClone)shallowClone.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(shallowClone == clone);//false
System.out.println(clone.getName());//Tom
System.out.println(clone.getAge());//18
System.out.println(shallowClone.getHobbies()==clone.getHobbies());//true
}
深克隆:
创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
测试代码
public static void main(String[] args) throws Exception{
//将对象写到流里
ShallowClone shallowClone = new ShallowClone();
shallowClone.setName("Tom");
shallowClone.setAge(18);
shallowClone.setHobbies(new ArrayList<>());
ByteArrayOutputStream byteOut=new ByteArrayOutputStream();
ObjectOutputStream objOut=new ObjectOutputStream(byteOut);
objOut.writeObject(shallowClone);
//从流里读出来
ByteArrayInputStream byteIn=new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream objInput=new ObjectInputStream(byteIn);
ShallowClone clone = (ShallowClone) objInput.readObject();
System.out.println(clone.getName());//Tom
System.out.println(clone.getAge());18
System.out.println(clone.getName() == shallowClone.getName());//false
System.out.println(clone.getHobbies() == shallowClone.getHobbies());//false
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1. "The Prototype design pattern - Problem, Solution, and Applicability". w3sDesign.com. Retrieved 2017-08-17.