【设计模式】原型模式

原型模式

         用原型模式指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

模型图

【设计模式】原型模式

 代码

public interface Prototype extends Cloneable {}
public class ConcreatePrototype1 implements Prototype{

	private ConcreatePrototype2 ConcreatePrototype2=null;
	
	public ConcreatePrototype2 getConcreatePrototype2() {
		return ConcreatePrototype2;
	}
	public void setConcreatePrototype2(ConcreatePrototype2 concreatePrototype2) {
		ConcreatePrototype2 = concreatePrototype2;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	private String filed1;
	
   	public ConcreatePrototype1(String filed1, String filed2) {
		super();
		this.filed1 = filed1;
		this.filed2 = filed2;
	}
	private String filed2;
   	
   	
	public String getFiled1() {
		return filed1;
	}
	public void setFiled1(String filed1) {
		this.filed1 = filed1;
	}
	public String getFiled2() {
		return filed2;
	}
	public void setFiled2(String filed2) {
		this.filed2 = filed2;
	}
	@Override
	public String toString() {
		return "ConcreatePrototype1 [ConcreatePrototype2="
				+ ConcreatePrototype2 + ", filed1=" + filed1 + ", filed2="
				+ filed2 + "]";
	}
}

 

public class ConcreatePrototype2 implements Prototype {
	private String filed;
	public String getFiled() {
		return filed;
	}

	public void setFiled(String filed) {
		this.filed = filed;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}

	@Override
	public String toString() {
		return "ConcreatePrototype2 [filed=" + filed + "]";
	}

	public ConcreatePrototype2(String filed) {
		super();
		this.filed = filed;
	}
}

 

 

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
		ConcreatePrototype1 concreatePrototype1=new ConcreatePrototype1("1","1");
		concreatePrototype1.setConcreatePrototype2(new ConcreatePrototype2("1"));
		System.out.println(concreatePrototype1);
	
		ConcreatePrototype1 clone = (ConcreatePrototype1) concreatePrototype1.clone();
		clone.getConcreatePrototype2().setFiled("2");
		System.out.println(clone);
    }
}

结果

【设计模式】原型模式

 

 案例 

需求  穿件一个份原始的简历,在不对原始简历做变更的情况下,快速创建出几分相同的简历来,这几分简历都在原始简历的基础上做微调

分析与设计 

 原始对象不做变更,基于原始对象,创建相同的对象适合原型模式

结构图

【设计模式】原型模式

 

代码

public interface ProtoType extends Cloneable {

}
public class Resume implements ProtoType{
	private String name;
	private int age;
	private int sex;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

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

	public Resume(String name, int age, int sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getSex() {
		return sex;
	}

	public void setSex(int sex) {
		this.sex = sex;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
}

 

public class Client {
   public static void main(String[] args) throws CloneNotSupportedException {
	   Resume resume=new Resume("张三",1,2);
	   System.out.println(resume);
	   
	   Resume clone = (Resume) resume.clone();
	   clone.setAge(3);
	   System.out.println(clone);
   }
}

【设计模式】原型模式

 

     深拷贝:复制一个对象,如果这个对象里面的字段是引用类型的,那么同样也拷贝这个引用类型,变更当前拷贝对象

引用类型的值。原引用对象的值不变

     浅拷贝:复制一个对象,如果这个对象里面的字段是引用类型的,那么拷贝的引用的对象的引用还是指向原有的对象,

更改当前拷贝对象,引用对象的值。原引用对象会跟着改变。

 

【设计模式】原型模式

 如上代码所示Java默认的原型模式是浅拷贝的如上图所示,我们修改了拷贝对象的引用对象的值以后。再次回去打印原对象的时候我们发现,concreteProTotype中的filed值已经不是1变成了2.这就证明所有的实例中的引用对象引用的是同一个对象。

那么我们怎么用java来实现深拷贝呢,两种方式

方式一 对象克隆方式

     修改原ConcretePrototype中的克隆方法,再对引用对象做一次浅拷贝,这种克隆方式,需要你对对象里面的多级调用都

再这个方法里进行浅拷贝,也就是递归的对象浅拷贝来实现对象的深拷贝。如果对象组合层次比较深的话,不建议使用这种方式来做深拷贝。也不具有通用性。

    

@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		ConcreatePrototype1 clone = (ConcreatePrototype1) super.clone();
		ConcreatePrototype2 concreatePrototype22 = (xiao.it.designer.prototype.model.ConcreatePrototype2) clone.getConcreatePrototype2().clone();
		clone.setConcreatePrototype2(concreatePrototype22);
		return clone;
	}

结果

【设计模式】原型模式

 如图所示成功的实现了深拷贝

方式二 序列化流的方式

public class ConcreatePrototype1 implements Serializable,Cloneable{
	private ConcreatePrototype2 ConcreatePrototype2=null;
	public ConcreatePrototype2 getConcreatePrototype2() {
		return ConcreatePrototype2;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		ObjectInputStream ois=null;
		try {
			// 序列化
		        ByteArrayOutputStream bos = new ByteArrayOutputStream();
		        ObjectOutputStream oos = new ObjectOutputStream(bos);
		        oos.writeObject(this);
		        // 反序列化
		        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
		         ois = new ObjectInputStream(bis);
		        if(null!=ois){
		 			return ois.readObject();
		 		}
		} catch (Exception e) {
			e.printStackTrace();
		}
        return null;
	}
	public void setConcreatePrototype2(ConcreatePrototype2 concreatePrototype2) {
		ConcreatePrototype2 = concreatePrototype2;
	}
	
	private String filed1;
	
   	public ConcreatePrototype1(String filed1, String filed2) {
		super();
		this.filed1 = filed1;
		this.filed2 = filed2;
	}
	private String filed2;
   	
   	
	public String getFiled1() {
		return filed1;
	}
	public void setFiled1(String filed1) {
		this.filed1 = filed1;
	}
	public String getFiled2() {
		return filed2;
	}
	public void setFiled2(String filed2) {
		this.filed2 = filed2;
	}
	@Override
	public String toString() {
		return "ConcreatePrototype1 [ConcreatePrototype2="
				+ ConcreatePrototype2 + ", filed1=" + filed1 + ", filed2="
				+ filed2 + "]";
	}
}

 如上代码所示,实现Serializable,Cloneable接口,对clone方法进行重写,就可以实现深拷贝了。这种方式可以写成一个公共的父类实现所有对象的深拷贝,推荐使用。

场景

    原始对象不做变更,基于原始对象,创建相同的对象适合原型模式