设计模式之-----原型模式

今天来学习设计模式中的原型模式,原型模式分为两种,一种是“浅复制”,一个是“深复制”。

先来说原型模式,原型模式说白了,就是一种复制模式,将已经新建好的对象,通过复制的形式,来给另一个对象赋值,在效率上,要远远好于new方式来实例化对象。

在复制的时候,会有一些问题,就是,默认的复制只会复制java的基本类型,包括String,但是对于类中的对象,只是复制它的引用,并没有从根本上去复制。举个例子:默认的复制方式就是,比如在内存中有一个值A,地址为1号(这里地址为假设的,为了方便所以这么写,真实的内存地址不是这样的),现在我声明了一个变量One,让这个变量One等于1号,最终的结果就是One=A,现在我用One克隆了一个Two,但是这个Two指向的地址也是1号,所以Two=A,表面上看没错,但是当Two操作这个A的时候,One里的A也会随着变化。不知道我说明白了没,我话一张图,大家就会明白许多。


看了这个图,我想大家会明白许多,所以不管是One还是Two,他们操作的是一个对象,One里修改,Two也会修改,反之也一样,这可不是我们想要的。我们想要的是下边的这个结果。


这才是我们要的结果,所以,原型模式就有了“浅复制”,“深复制”的区别。

我们来看一看怎么实现

包结构


先看看浅复制

新建一个people方法,存放人的姓名和年龄

package com.prototype.shallow.clone;

public class People implements Cloneable {

	private String peopleName;
	private int peopleAge;
	
	public People() {
		super();
		System.out.println("执行了People的构造方法");
	}

	public String getPeopleName() {
		return peopleName;
	}

	public void setPeopleName(String peopleName) {
		this.peopleName = peopleName;
	}

	public int getPeopleAge() {
		return peopleAge;
	}

	public void setPeopleAge(int peopleAge) {
		this.peopleAge = peopleAge;
	}

	public Object clone() {
		People people = null;
		try {
			people = (People) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return people;
	}
}

注意这里要实现一个Cloneable接口,然后要写一个Clone方法,调用Object的clone方法,很简单

来看一下怎么调用

package com.prototype.shallow.main;

import com.prototype.shallow.clone.People;

public class ShallowMain {

	public static void main(String[] args) {
		People people1 = new People();
		people1.setPeopleName("小明");
		people1.setPeopleAge(20);
		
		
		//克隆第二个对象
		People people2 = (People) people1.clone();
		people2.setPeopleAge(30);
<pre name="code" class="java">                System.out.println("姓名:"+people1.getPeopleName()+",年龄:"+people1.getPeopleAge());
  System.out.println("姓名:"+people2.getPeopleName()+",年龄:"+people2.getPeopleAge());}}

 运行结果如下 


是不是很简单?而且要注意,上边的构造方法值执行了一次,所以克隆方法是不会再去执行构造方法的,是直接对jvm的数据操作,效率当然比new这种方式高很多。


如果,这个people对象里有其他对象存在的话,上边的这个方法就行不通了,这时就要用到深复制了

还是上边的那个例子

package com.prototype.deep.clone;

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 People implements Cloneable,Serializable{

	private static final long serialVersionUID = 1L;
	
	private String peopleName;
	private int peopleAge;

	private WorkExperience workExperience;

	public People() {
		super();
		System.out.println("执行了People的构造方法");
	}

	public String getPeopleName() {
		return peopleName;
	}

	public void setPeopleName(String peopleName) {
		this.peopleName = peopleName;
	}

	public int getPeopleAge() {
		return peopleAge;
	}

	public void setPeopleAge(int peopleAge) {
		this.peopleAge = peopleAge;
	}

	public WorkExperience getWorkExperience() {
		return workExperience;
	}

	public void setWorkExperience(WorkExperience workExperience) {
		this.workExperience = workExperience;
	}

	public Object deepClone() throws IOException, ClassNotFoundException {
		//将对象写到流里
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        //从流里读回来
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
	}
}

我在people里增加了一个对象,而且注意,我该写了deepClone方法,这才是深复制的区别所在

WorkExperience类,工作经历类

package com.prototype.deep.clone;

import java.io.Serializable;

public class WorkExperience implements Serializable {

	private static final long serialVersionUID = 1L;

	private String companyName;
	private double workTime;

	public WorkExperience() {
		super();
		System.out.println("执行了WorkExperience的构造方法");
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	public double getWorkTime() {
		return workTime;
	}

	public void setWorkTime(double workTime) {
		this.workTime = workTime;
	}

}

调用的时候和之前差不多

package com.prototype.deep.main;

import com.prototype.deep.clone.People;
import com.prototype.deep.clone.WorkExperience;

public class DeepMain {

	public static void main(String[] args) {
		People people1 = new People();
		WorkExperience workExperience = new WorkExperience();
		workExperience.setCompanyName("XXX公司");
		workExperience.setWorkTime(2.5);
		people1.setPeopleName("小明");
		people1.setPeopleAge(20);
		people1.setWorkExperience(workExperience);
		
		People people2 = null;
		try {
			people2 = (People) people1.deepClone();
			people2.getWorkExperience().setWorkTime(10.5);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("姓名:"+people1.getPeopleName()+",年龄:"+people1.getPeopleAge()+",工作公司:"+people1.getWorkExperience().getCompanyName()+",工作年限:"+people1.getWorkExperience().getWorkTime());
		System.out.println("姓名:"+people2.getPeopleName()+",年龄:"+people2.getPeopleAge()+",工作公司:"+people2.getWorkExperience().getCompanyName()+",工作年限:"+people2.getWorkExperience().getWorkTime());
	}

}

运行结果


这里才达到了我们的要求。

同时要注意,要进行复制的对象一定要实现Serializable接口,否则会抛异常。


一般来说,原型模式单独来用的情况不是很多,通常会和其他模式混合使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值