由于 Java 提供了对象的 clone() 方法,所以用 Java 实现原型模式很简单。
1. 模式的结构
原型模式包含以下主要角色。
- 抽象原型类:规定了具体原型对象必须实现的接口。
- 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
其结构图如图 1 所示。
原型模式的结构图2. 实现深拷贝的几种方法
2.1 clone方法
@Data
public class Company implements Cloneable{
/**
* 公司唯一标识
*/
private String companyId;
/**
* 公司名称
*/
private String companyName;
/**
* 成立时间
*/
private Date startDate;
/**
* 行业
*/
private String industry;
/**
* 员工列表
*/
private List<Colleague> colleagueList;
@Override
public Company clone(){
Company newCompany = null;
try {
newCompany = (Company)super.clone();
List<Colleague> newColleagueList = new ArrayList<>();
for (Colleague colleague : colleagueList) {
newColleagueList.add((Colleague)colleague.clone());
}
newCompany.setColleagueList(newColleagueList);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return newCompany;
}
}
@Data
public class Colleague implements Cloneable{
/**
* 工号
*/
private String jobNumber;
/**
* 姓名
*/
private String userName;
/**
* 生日
*/
private Date birthday;
/**
* 年龄
*/
private Integer age;
/**
* 薪资
*/
private Double salary;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
2.2 json
通过fastjson实现
@Data
public class Company implements Cloneable{
public Company(String companyId, String companyName, String industry, List<Colleague> colleagueList) {
this.companyId = companyId;
this.companyName = companyName;
this.industry = industry;
this.colleagueList = colleagueList;
}
public Company(){
}
/**
* 公司唯一标识
*/
private String companyId;
/**
* 公司名称
*/
private String companyName;
/**
* 成立时间
*/
private Date startDate;
/**
* 行业
*/
private String industry;
/**
* 员工列表
*/
private List<Colleague> colleagueList;
@Override
public Company clone(){
Company newCompany = null;
try {
newCompany = (Company)super.clone();
List<Colleague> newColleagueList = new ArrayList<>();
for (Colleague colleague : colleagueList) {
newColleagueList.add((Colleague)colleague.clone());
}
newCompany.setColleagueList(newColleagueList);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return newCompany;
}
public static void main(String[] args) {
List<Colleague> colleagueList = new ArrayList<>();
colleagueList.add(new Colleague("123","晓明"));
colleagueList.add(new Colleague("456","baby"));
Company sourceCompany = new Company("12345", "企查查", "查询",colleagueList);
Company targetCompany = JSON.parseObject(JSON.toJSONString(sourceCompany), Company.class);
System.out.println("sourceCompany:"+JSON.toJSONString(sourceCompany)
+",targetCompany:"+JSON.toJSONString(targetCompany)
+",sourceCompany == targetCompany:"+(sourceCompany == targetCompany));
System.out.println("colleagueList:"+JSON.toJSONString(colleagueList)
+",newColleagueList:"+targetCompany.colleagueList
+",colleagueList == newColleagueList:"+(colleagueList == targetCompany.colleagueList));
}
}
@Data
public class Colleague implements Cloneable{
public Colleague(String jobNumber, String userName) {
this.jobNumber = jobNumber;
this.userName = userName;
}
public Colleague(){
}
/**
* 工号
*/
private String jobNumber;
/**
* 姓名
*/
private String userName;
/**
* 生日
*/
private Date birthday;
/**
* 年龄
*/
private Integer age;
/**
* 薪资
*/
private Double salary;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
输出:
sourceCompany:{"colleagueList":[{"jobNumber":"123","userName":"晓明"},{"jobNumber":"456","userName":"baby"}],"companyId":"12345","companyName":"企查查","industry":"查询"},targetCompany:{"colleagueList":[{"jobNumber":"123","userName":"晓明"},{"jobNumber":"456","userName":"baby"}],"companyId":"12345","companyName":"企查查","industry":"查询"},sourceCompany == targetCompany:false
colleagueList:[{"jobNumber":"123","userName":"晓明"},{"jobNumber":"456","userName":"baby"}],newColleagueList:[Colleague(jobNumber=123, userName=晓明, birthday=null, age=null, salary=null), Colleague(jobNumber=456, userName=baby, birthday=null, age=null, salary=null)],colleagueList == newColleagueList:false
拷贝的对象与原来对象属性值一样,但是不指向同一内存区域
2.3 序列化和反序列化
Company和Colleague都实现Serializable接口
List<Colleague> colleagueList = new ArrayList<>();
colleagueList.add(new Colleague("123","晓明"));
colleagueList.add(new Colleague("456","baby"));
Company sourceCompany = new Company("12345", "企查查", "查询",colleagueList);
Company targetCompany = null;
try
{
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try
{
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(sourceCompany);
oos.flush();
}
finally
{
oos.close();
}
byte[] bytes = bos.toByteArray();
ObjectInputStream ois = null;
try
{
ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
targetCompany = (Company)ois.readObject();
}
finally
{
ois.close();
}
System.out.println("sourceCompany:"+JSON.toJSONString(sourceCompany)
+",targetCompany:"+JSON.toJSONString(targetCompany)
+",sourceCompany == targetCompany:"+(sourceCompany == targetCompany));
System.out.println("colleagueList:"+JSON.toJSONString(colleagueList)
+",newColleagueList:"+targetCompany.colleagueList
+",colleagueList == newColleagueList:"+(colleagueList == targetCompany.colleagueList));
}
catch(Exception e)
{
e.printStackTrace();//克隆失败
}
2.4 工具类
List<Colleague> colleagueList = new ArrayList<>();
colleagueList.add(new Colleague("123","晓明"));
colleagueList.add(new Colleague("456","baby"));
Company sourceCompany = new Company("12345", "企查查", "查询",colleagueList);
Company targetCompany = new Company();
BeanUtils.copyProperties(sourceCompany, targetCompany);
System.out.println("sourceCompany:"+JSON.toJSONString(sourceCompany)
+",targetCompany:"+JSON.toJSONString(targetCompany)
+",sourceCompany == targetCompany:"+(sourceCompany == targetCompany));
System.out.println("colleagueList:"+JSON.toJSONString(colleagueList)
+",newColleagueList:"+targetCompany.colleagueList
+",colleagueList == newColleagueList:"+(colleagueList == targetCompany.colleagueList));
这个方法只能实现浅拷贝,不能实现深拷贝
网友评论