Java设计模式–原型模式
-
定义
指原型实例指定创建对象的种类,并且通过拷贝这些原型创建的新对象 -
实现
public class PortotypeTest {
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
BaseInfo baseInfo=new BaseInfo("xxx");
Product product = new Product("part1", "part2", "part3", "part4", "part5",baseInfo);
//一些其他操作。。。
Product clone = product.clone();
System.out.println("original"+product);
System.out.println("clone "+clone);
product.getBaseInfo().setCompanyName("yyyy");
System.out.println("original"+product);
System.out.println("clone "+clone);
}
}
class Product implements Cloneable{
private String part1;
private String part2;
private String part3;
private String part4;
private String part5;
private BaseInfo baseInfo;
//...其他模块
public Product() {
}
public Product(String part1, String part2, String part3, String part4, String part5,BaseInfo baseInfo) {
super();
this.part1 = part1;
this.part2 = part2;
this.part3 = part3;
this.part4 = part4;
this.part5 = part5;
this.baseInfo=baseInfo;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
public String getPart4() {
return part4;
}
public void setPart4(String part4) {
this.part4 = part4;
}
public String getPart5() {
return part5;
}
public void setPart5(String part5) {
this.part5 = part5;
}
public BaseInfo getBaseInfo() {
return baseInfo;
}
public void setBaseInfo(BaseInfo baseInfo) {
this.baseInfo = baseInfo;
}
@Override
protected Product clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (Product) super.clone();
}
@Override
public String toString() {
return super.hashCode()+"Product [part1=" + part1 + ", part2=" + part2 + ", part3=" + part3 + ", part4=" + part4 + ", part5="
+ part5 + ", baseInfo=" + baseInfo + "]";
}
}
class BaseInfo{
private String companyName;
public BaseInfo() {
}
public BaseInfo(String companyName) {
this.companyName=companyName;
}
@Override
public String toString() {
return super.hashCode()+"BaseInfo [companyName=" + companyName + "]";
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
}
结论:克隆的对象和创建的对象的属性一致,但是对比两个对象,其实是不同的,如果对象中有其他类的对象,那么,这些数据是可以共享的。
原因:在对于可变对象,执行的是浅拷贝
(tips:如果你是基本数据类型或者是不可变的对象,直接super.clone()就可以了<源码>)
但是这样是不合理的,于是给出如下解决方案在BaseInfo类也实现Cloneable接口实现clone()方法并修改Product中的clone()方法
public class PortotypeTest {
public static void main(String[] args) throws CloneNotSupportedException {
// TODO Auto-generated method stub
BaseInfo baseInfo=new BaseInfo("xxx");
Product product = new Product("part1", "part2", "part3", "part4", "part5",baseInfo);
//一些其他操作。。。
Product clone = product.clone();
System.out.println("original"+product);
System.out.println("clone "+clone);
product.getBaseInfo().setCompanyName("yyyy");
System.out.println("original"+product);
System.out.println("clone "+clone);
}
}
class Product implements Cloneable{
private String part1;
private String part2;
private String part3;
private String part4;
private String part5;
private BaseInfo baseInfo;
//...其他模块
public Product() {
}
public Product(String part1, String part2, String part3, String part4, String part5,BaseInfo baseInfo) {
super();
this.part1 = part1;
this.part2 = part2;
this.part3 = part3;
this.part4 = part4;
this.part5 = part5;
this.baseInfo=baseInfo;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
public String getPart4() {
return part4;
}
public void setPart4(String part4) {
this.part4 = part4;
}
public String getPart5() {
return part5;
}
public void setPart5(String part5) {
this.part5 = part5;
}
public BaseInfo getBaseInfo() {
return baseInfo;
}
public void setBaseInfo(BaseInfo baseInfo) {
this.baseInfo = baseInfo;
}
@Override
protected Product clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
Product clone=(Product) super.clone();
BaseInfo clone2 = this.baseInfo.clone();
clone.setBaseInfo(clone2);
return clone;
}
@Override
public String toString() {
return super.hashCode()+"Product [part1=" + part1 + ", part2=" + part2 + ", part3=" + part3 + ", part4=" + part4 + ", part5="
+ part5 + ", baseInfo=" + baseInfo + "]";
}
}
class BaseInfo implements Cloneable{
private String companyName;
public BaseInfo() {
}
public BaseInfo(String companyName) {
this.companyName=companyName;
}
@Override
public String toString() {
return super.hashCode()+"BaseInfo [companyName=" + companyName + "]";
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
@Override
protected BaseInfo clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (BaseInfo) super.clone();
}
}
运行结束后,我们发现此时仅仅针对main方法中的product的companyName做出了改变,这只是实现深拷贝的一种实现方式,这里再提供一种思路,就是序列化
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class PortotypeTest {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
BaseInfo baseInfo=new BaseInfo("xxx");
Product product = new Product("part1", "part2", "part3", "part4", "part5",baseInfo);
//一些其他操作。。。
Product clone = product.clone();
System.out.println("original"+product);
System.out.println("clone "+clone);
product.getBaseInfo().setCompanyName("yyyy");
System.out.println("original"+product);
System.out.println("clone "+clone);
}
}
class Product implements Cloneable,Serializable{
private static final long serialVersionUID = 42L;
private String part1;
private String part2;
private String part3;
private String part4;
private String part5;
private BaseInfo baseInfo;
//...其他模块
public Product() {
}
public Product(String part1, String part2, String part3, String part4, String part5,BaseInfo baseInfo) {
super();
this.part1 = part1;
this.part2 = part2;
this.part3 = part3;
this.part4 = part4;
this.part5 = part5;
this.baseInfo=baseInfo;
}
public String getPart1() {
return part1;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public String getPart2() {
return part2;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public String getPart3() {
return part3;
}
public void setPart3(String part3) {
this.part3 = part3;
}
public String getPart4() {
return part4;
}
public void setPart4(String part4) {
this.part4 = part4;
}
public String getPart5() {
return part5;
}
public void setPart5(String part5) {
this.part5 = part5;
}
public BaseInfo getBaseInfo() {
return baseInfo;
}
public void setBaseInfo(BaseInfo baseInfo) {
this.baseInfo = baseInfo;
}
@Override
protected Product clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
try(ObjectOutputStream oos=new ObjectOutputStream(byteArrayOutputStream);){
oos.writeObject(this);
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
try(ObjectInputStream ois=new ObjectInputStream(byteArrayInputStream)){
Product clone=(Product) ois.readObject();
return clone;
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return super.hashCode()+"Product [part1=" + part1 + ", part2=" + part2 + ", part3=" + part3 + ", part4=" + part4 + ", part5="
+ part5 + ", baseInfo=" + baseInfo + "]";
}
}
class BaseInfo implements Cloneable,Serializable{
private static final long serialVersionUID = 42L;
private String companyName;
public BaseInfo() {
}
public BaseInfo(String companyName) {
this.companyName=companyName;
}
@Override
public String toString() {
return super.hashCode()+"BaseInfo [companyName=" + companyName + "]";
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
@Override
protected BaseInfo clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return (BaseInfo) super.clone();
}
}
序列化同样实现了深拷贝,但是这个并不是很推荐,一方面,序列化的过程比较慢,其次对序列化的不熟悉也会造成不理想的结果,当然,你还可以像Cloneable一样写一个属于自己的接口。。。实现一个功能的方法有很多,就不一一列举了。。。
-
应用场景
当代码不应依赖于需要复制的对象的具体类时,请使用Prototype模式 -
优点
-
1.可以不耦合具体类的情况下克隆对象
2 .避免重复的初始化代码
3.更方便的构造复杂对象 -
源码中的应用
-
1.org.springframework.beans.factory.support.AbstractBeanDefinition 2.java.util.Arrays
本文深入探讨Java设计模式中的原型模式,解析如何通过拷贝原型对象创建新实例,避免重复初始化,实现复杂对象的高效克隆。并通过代码示例,演示浅拷贝与深拷贝的区别及实现方式。
210





