原型模式

设计模式

原型模式

定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的对象。

特点:

​ 1、简化对象创建的流程,同时也可以提高效率

​ 2、如果原始对象发生变化,其克隆对象也会发生相应变化,无需修改代码

劣势:

​ 1、每个对象都需要配备一个克隆方法,违反OCP(开闭)原则

原型模式的拷贝分为浅拷贝深拷贝

浅拷贝
对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递
对于数据类型是引用数据类型的成员变量,那么浅拷贝会进行引用传递

以打印简历为例:

package com.prototype;

public class Resume implements Cloneable{
    private String name;
    private boolean sex;
    private String salary;
 	private Witness witness;//见证人
    /*
       简历类
       
       浅拷贝:
       1. 实现Cloneable接口
       2. 重写clone()方法
    */
    //略写有参无参构造方法,set、get方法 
    
    //重写clone方法
	protected Object clone() throws CloneNotSupportedException {
		System.out.println("复制简历成功!!");
		Resume clone = (Resume) super.clone();
		return clone;
	}

	@Override
	public String toString() {
		return "Resume [name=" + name + ", sex=" + sex + ", salary=" + salary
				+ "]";
	}
	  
}

package com.prototype;
//客户端
public class Client {
   public static void main(String[] args) {
	  Resume resume = new Resume("jack", true, "面试");
	  resume.setWitness(new Witness("mary", "经理"));
	  //打印2份简历
	  for (int i = 0; i < 2; i++) {
		try {
			Resume clone = (Resume) resume.clone();
			System.out.println("打印简历:"+clone);
			System.out.println("resume的哈希值"+clone.hashCode());
			System.out.println("witness的哈希值"+clone.getWitness().hashCode());
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		}
   }
}

package com.prototype;
//见证人 类
public class Witness{
   private String name;//姓名
   private String job;//职位
   
//略写有参无参构造方法,set、get方法
    
@Override
public String toString() {
	return "Witness [name=" + name + ", job=" + job + "]";
}
   
}

显示:
复制简历成功!!
打印简历:Resume [name=jack, sex=true, salary=面试, witness=Witness [name=mary, job=经理]]
resume的哈希值1167165921
witness的哈希值1442002549

复制简历成功!!
打印简历:Resume [name=jack, sex=true, salary=面试, witness=Witness [name=mary, job=经理]]
resume的哈希值1383884648
witness的哈希值1442002549

结果:resume克隆对象的内容一样,但不是同一个对象,其中属性witness进行的是引用传递
深拷贝:

实现方式1:重写clone()方法(不推荐)

缺点:虽然层次调用clone方法可以实现深拷贝,但是显然代码量实在太大。特别对于属性数量比较多、层次比较深的类而言,每个类都要重写clone方法太过繁琐。

也是以打印简历为例:

package com.prototype;

public class Resume2 implements Cloneable{
    //简历2.0版本
	private String name;
	private int age;
	private String salary;
	private Witness witness;
	
	//略写有参无参构造方法,set、get方法

	@Override
	protected Object clone() throws CloneNotSupportedException {
        /*
         * 完成深拷贝
         * 实现方式1:重写clone()方法
         * */
        //第一步:完成对基本数据类型或String类型的拷贝
		Resume2 resume2 = (Resume2)super.clone();
		//第二步:对引用类型进行处理(引用类型也要实现Cloneable接口,重写clone方法)
		resume2.witness = (Witness) witness.clone();
		
		return resume2;
	}
}

   package com.prototype;
   //见证人 类
   public class Witness implements Cloneable{
   private String name;
   private String job;
    
	//略写有参无参构造方法,set、get方法 ,toString方法  
    
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return (Witness)super.clone();
	}

    @Override
    public String toString() {
        return "Witness [name=" + name + ", job=" + job + "]";
    }
   
}

package com.prototype;

public class Client2 {
   public static void main(String[] args) {
	 Resume2 resume2 = new Resume2("jack", 20, "面议");
	 resume2.setWitness(new Witness("mary", "经理"));
	 
	 for (int i = 0; i < 2; i++) {
		try {
			Resume2 clone1 = (Resume2) resume2.clone();
			System.out.println("打印简历:"+clone1);
			System.out.println("clone1的哈希值:"+clone1.hashCode());
			System.out.println("witness的哈希值:"+clone1.getWitness().hashCode());
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}
   }
}

显示:
打印简历:Resume2 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
clone1的哈希值:1167165921
witness的哈希值:1442002549

打印简历:Resume2 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
clone1的哈希值:1383884648

实现方式2:通过对象序列化(推荐)

特点:一步到位不管类的结构和如何复杂,整体处理

注意:如果某个属性被transient修饰,那么该属性就无法被拷贝了

步骤:1.要进行拷贝的类要实现Serializable接口 2.进行序列化与反序列化

package com.prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Resume3 implements Serializable{
    //简历 3.0版本
	private String name;
	private int age;
	private String salary;
	private Witness witness;//Witness类也要实现Serializable接口
	
	//set get方法,有参无参构造函数略写

    //对象序列化与反序列化
	public Resume3 deepClone(){
		ByteArrayOutputStream bos = null;
		ByteArrayInputStream bis = null;
		ObjectOutputStream oos = null;
		ObjectInputStream ois = null;
		Resume3 resume3 = null;
		try {
			//对象序列化
			bos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bos);
			oos.writeObject(this);
			//反序列化
			bis = new ByteArrayInputStream(bos.toByteArray());
			ois = new ObjectInputStream(bis);
			resume3 = ois.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}finally{
			try {
				//关闭流
				bos.close();
				oos.close();
				bis.close();
				ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		
		return resume3;
	}
	@Override
	public String toString() {
		return "Resume3 [name=" + name + ", age=" + age + ", salary=" + salary
				+ ", witness=" + witness + "]";
	}
	
}

package com.prototype;

import java.io.Serializable;

public class Witness implements Serializable{
   private String name;
   private String job;
    
//略写set get toString方法
   
}

package com.prototype;
//客户端
public class Client3 {
   public static void main(String[] args) {
	  Resume3 resume3 = new Resume3("jack", 20, "面议");
	  resume3.setWitness(new Witness("mary", "经理"));
	  Resume3 d1 =  resume3.deepClone();
	  Resume3 d2 =  resume3.deepClone();
	  System.out.println(d1);
	  System.out.println(d2);
	  System.out.println(d1.hashCode()+"   "+d2.hashCode());
	  System.out.println(d1.getWitness().hashCode()+" "+d2.getWitness().hashCode());
   }
}

显示:
Resume3 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
Resume3 [name=jack, age=20, salary=面议, witness=Witness [name=mary, job=经理]]
1932154105   1613816448
694579926  83711190
posted @ 2021-04-07 20:27  wwww2  阅读(102)  评论(0编辑  收藏  举报