Java设计模式--原型模式

本文深入探讨Java设计模式中的原型模式,解析如何通过拷贝原型对象创建新实例,避免重复初始化,实现复杂对象的高效克隆。并通过代码示例,演示浅拷贝与深拷贝的区别及实现方式。

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
    
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值