23种设计模式笔记第五篇原型模式(参考狂神视频)

原型模式就是以某个东西为原型,将它进行拷贝。(也就是复制粘贴的思想)

目录

原型模式的定义(Prototype Pattern)

原型模式的适用场景

浅拷贝和深拷贝

实现步骤(浅拷贝)

实现步骤(深拷贝)

原型模式的应用

原型模式的优缺点


扫描二维码关注公众号,回复: 14124420 查看本文章

原型模式的定义(Prototype Pattern)

原型模式是一种对象创建型模式, 用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象
原型模式允许通过一个原型对象创建一个或多个同类型的其他对象,而无须知道任何创建的细节

模式动机

1、复制一个对象,从而克隆出多个与原型对象一模一样的对象——原型模式

2、有些对象的创建过程较为复杂,而且需要频繁创建

3、通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象

与new的区别:克隆有cloneable接口和clone()方法,new相当于创造了一个新的对象,会有原本的默认值,而克隆是直接拷贝了一个对象,完全一致。

原型模式的适用场景

在以下情况下可以使用原型模式:

 1创建新对象成本较大,新对象可以通过复制已有对象来获得,如果是相似对象,则可以对其成员变量稍作修改(或者是对象比较复杂的情况)

2、系统要保存对象的状态,而对象的状态变化很小

 3、需要避免使用分层次的工厂类来创建分层次的对象

浅拷贝和深拷贝

浅拷贝:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,浅拷贝并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性)。
深拷贝:深拷贝是在浅拷贝的基础上,递归地克隆除8种基本数据类型和String类型外的属性(即为这些属性重新分配内存而非引用原来对象中的属性)

深拷贝简单的理解就是在浅拷贝的基础上,进一步对对象属性进行依次拷贝,对象里面的复杂属性也重新生成了新的引用。

浅拷贝中由于除8中数据类型和String类型外的其他类型的属性不会被克隆,因此当通过新对象对这些属性进行修改时,原对象的属性也会同时改变。而深拷贝则已经对这些属性重新分配内存,所以当通过新对象对这些属性进行修改时,原对象的属性不会改变。

如图:

深拷贝实现方式:

序列化和反序列化就可以实现(效率低一点);改造clone()方法也可以实现(违背开闭原则);

序列化:把对象转换为字节序列的过程称为对象的序列化。

反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

实现步骤(浅拷贝)

简单的两步:实现一个接口Cloneable,重写一个方法clone()

这里以克隆视频为例

 import java.util.Date;

public class Video implements Cloneable {

	private String name;
	private Date createTime;
	
	//clone是本地方法(native)
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	
	public Video() {
		
	}

	public Video(String name, Date createTime) {
		this.name = name;
		this.createTime = createTime;
	}

	public String getName() {
		return name;
	}

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

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}
}
import java.util.Date;

//客户端克隆
public class ClientCopy {

	public static void main(String[] args) throws CloneNotSupportedException {
		//创建原型对象 v1
		Date date = new Date();
		Video v1 = new Video("宋浩讲高数",date);
		System.out.println("v1="+v1.getName());
		System.out.println("v1="+v1.getCreateTime());
		System.out.println("v1=>hash="+v1.hashCode());
		//v2克隆v1
		Video v2 = (Video)v1.clone();
		System.out.println("v2="+v2.getName());
		System.out.println("v2="+v2.getCreateTime());
		System.out.println("v2=>hash="+v2.hashCode());
	}
}

这里的hash值不一样说明它们是两个对象,在内存中的存储位置不同,hash值的计算是通过对象在内存中的逻辑地址进行加工变换的。

date的一个复杂属性,如果改变其中一个的date,那么另外一个的date也会改变

import java.util.Date;

//客户端克隆
public class ClientCopy {

	public static void main(String[] args) throws CloneNotSupportedException {
		//创建原型对象 v1
		Date date = new Date();
		Video v1 = new Video("宋浩讲高数",date);
		System.out.println("v1="+v1.getName());
		System.out.println("v1="+v1.getCreateTime());
		System.out.println("v1=>hash="+v1.hashCode());
		//v2克隆v1
		Video v2 = (Video)v1.clone();
		System.out.println("v2="+v2.getName());
		System.out.println("v2="+v2.getCreateTime());
		System.out.println("v2=>hash="+v2.hashCode());
		//改变v1的name和date属性:
		System.out.println("-------------------------------");
		v1.setName("mouse");
		date.setTime(2332322);
		System.out.println("v1="+v1.getName());
		System.out.println("v1="+v1.getCreateTime());
		System.out.println("v1=>hash="+v1.hashCode());
		System.out.println("v2="+v2.getName());
		System.out.println("v2="+v2.getCreateTime());
		System.out.println("v2=>hash="+v2.hashCode());
	}
}

 可以看到,v2的name属性没有改变,但是date改变了。这就是浅拷贝

实现步骤(深拷贝)

这里以改造clone()方法为例:

	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();
		Video v = (Video)obj;
		//将对象的属性也进行克隆(实现深克隆)
		v.createTime = (Date)this.createTime.clone();
		return obj;
	}
	

原型模式的应用

Spring的bean的创建就应用了原型模式和单例模式

原型模式也会跟工厂模式打交道,之前工厂模式是new,现在可以使用拷贝

原型模式的优缺点

优点:

1简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率

2扩展性较好

3、简化创建结构,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品

4、可以使用深克隆的方式保存对象的状态,以便在需要的时候使用,可辅助实现撤销操作

缺点:

       1需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了开闭原则

        2、在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦

猜你喜欢

转载自blog.csdn.net/qq_44709970/article/details/124418163