【设计模式】原型模式

原型模式

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

模型图

 代码

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 abstract class Serializers<T> {

	public abstract T read(byte[] buf) throws IOException, ClassNotFoundException;
	
	public abstract byte[] wirte(T t) throws IOException;

}

序列化工具

/**
 * 
 */
package com.java;

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

/**
 * @author pc
 * @param <T>
 *
 */
public class SerializeUtils<T> extends Serializers<T> {

	private static SerializeUtils serializeUtils=null;
	
	private SerializeUtils() {
		
	}
	
	public static SerializeUtils getInstance() {
		if(null==serializeUtils) {
			synchronized (SerializeUtils.class) {
				if(null==serializeUtils) {
					serializeUtils=new SerializeUtils();
				}
			}
		}
		return serializeUtils;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.java.Serializers#read(byte[])
	 */
	@Override
	public T read(byte[] buf) throws IOException, ClassNotFoundException {
		ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(buf);
		ObjectInputStream inputStream = new ObjectInputStream(arrayInputStream);
		T readObject = (T) inputStream.readObject();
		return readObject;
	}

	
	@Override
	public byte[] wirte(T t) throws IOException {
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
		outputStream.writeObject(t);
		byte[] byteArray = byteArrayOutputStream.toByteArray();
		return byteArray;
	}

}

对象类记得实现Serializable接口

/**
 * 
 */
package com.java;

import java.io.Serializable;

/**
 * @author pc
 *
 */
public class User implements Serializable{
	private int no;
	private String name;
	private String age;
	
	public User() {
		
	}

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

	public User(int no,String name,String age) {
		this.no=no;
		this.name=name;
		this.age=age;
	}
	
	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

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

	public String getAge() {
		return age;
	}

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

}

测试类 

public class SerializeTest {
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		 User user=new User(123, "xiaozhengwen", "xxxx");
		 //定义
		 byte[] wirte = SerializeUtils.getInstance().wirte(user);
		 System.out.println(Arrays.toString(wirte));
		 
		 User read = (User) SerializeUtils.getInstance().read(wirte);
		 System.out.println(read);
		 
	}
}

测试结果

 

由上图可以看出实际上对象的序列化,就是把对象转化成,字节码的流文件。再通过字节码把的流文件进行

解析,反序列化成对象。说完了序列化以后,我们再来看通过序列化进行对象的深拷贝的方法。

方式二 序列化流的方式

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方法进行重写,就可以实现深拷贝了。这种方式可以写成一个公共的父类实现所有对象的深拷贝,推荐使用。

场景

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

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值