• 原型模式


    @

    一、原型模式

    Prototype模式是一种对象创建型模式,通过复制自己进行创建。

    (一)、原型模式的特点

    1. 由原型对象自身创建目标对象,也就是说,对象创建这一动作发自原型对象本身。
    2. 目标对象是原型对象的一个克隆。通过Prottype模式创建的对象,不仅仅与目标对象具有相同的结构,还与目标对象具有相同的值
    3. 根据对象克隆深层次的不同,有浅度克隆与深度克隆

    二、原型模式具体实现

    (一)、克隆与复制的区别

    克隆是指将一个对象复制出另一个对象信息相同的对象,并且他们的内存地址是不相同的,在堆中的对象信息相同但不是同一个;赋值只是改变了变量之间内存地址的指向。
    在这里插入图片描述

    (二)、如何实现克隆?

    1. 第一步:实现Cloneable接口
    2. 第二步:重写Object中的clone()方法
    package 原型模式;
    //	第一步实现Cloneable接口
    public class Student implements Cloneable{
    	private int id;
    	private String name;
    	private String Sex;
    	public int getId() {
    		return id;
    	}
    	public void setId(int id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getSex() {
    		return Sex;
    	}
    	public void setSex(String sex) {
    		Sex = sex;
    	}
    //	重写Object中的clone()方法
    	@Override
    	protected Student clone() throws CloneNotSupportedException {
    		return (Student) super.clone();
    	}
    	
    }
    

    调用一下,克隆是否成功?

    package 原型模式;
    
    public class Maintest {
    	public static void main(String[] args) {
    		System.out.println("      浅度克隆!");
    		Student s1 = new Student();
    		s1.setId(1);
    		s1.setName("张三");
    		s1.setSex("男");
    		System.out.printf("S1指向内存地址:"+s1+"----");
    		System.out.println("S1信息:"+"	id:"+s1.getId()
    		+"	name:"+s1.getName()+"	sex"+s1.getSex());
    		/* 克隆s1 */
    		System.out.println("-----------------------------------------");
    		// s1要调用克隆方法
    		try {
    			Student s2 = s1.clone();
    			System.out.printf("S2指向内存地址:"+s2+"----");
    			System.out.println("S2信息:"+"	id:"+s2.getId()
    			+"	name:"+s2.getName()+"	sex:"+s2.getSex());
    		} catch (CloneNotSupportedException e) {
    			e.printStackTrace();
    		}
    		
    	}
    }
    
    

    打印信息:在打印信息中可以看S1和S2指向的内存地址是不同的,而两块内存地址所存储的信息是相同的,这就是克隆,而这只是浅度的克隆!浅度只能实现基本数据类型的克隆,而不能实现
    在这里插入图片描述

    深度克隆

    通过上个案例我们看到了,浅度克隆的实现,克隆中也是区分层次的,浅度克隆只是针对基本数据类型的属性有效,对于复合数据类型就没有效果!通过案例来看一下,创建Student1对象添加一个数组属性,然后进行对象克隆,看一看数组的地址是否相同!

    package 原型模式;
    
    import java.util.List;
    //第一步实现Cloneable接口
    public class Student1 implements Cloneable{
    	private String[] arr = new String[2];
    	public String[] getArr() {
    		return arr;
    	}
    	public void setArr(String[] arr) {
    		this.arr = arr;
    	}
    	//	重写Object中的clone()方法
    	@Override
    	protected Student1 clone() throws CloneNotSupportedException {
    		return (Student1) super.clone();
    	}	
    }
    
    
    package 原型模式;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Test {
    public static void main(String[] args) {
    	Student1 s1 = new Student1();
    	String[] arr = new String[2];
    	arr[0]="数组";
    	arr[1]="数据";
    	s1.setArr(arr);
    	System.out.println("s1地址:"+s1);
    	System.out.println("s1数组地址:"+s1.getArr());
    	System.out.println("存储信息:"+s1.getArr()[0]+"、"+s1.getArr()[1]);
    	
    	System.out.println("---------------------------------------------");
    	
    	try {
    		Student1 s2 = s1.clone();
    		System.out.println("s2地址:"+s2);
    		System.out.println("s2-集合地址:"+s2.getArr());
    		System.out.println("存储信息:"+s2.getArr()[0]+"、"+s2.getArr()[1]);
    	} catch (CloneNotSupportedException e) {
    		e.printStackTrace();
    	}
    }
    }
    

    打印后的结果:
    在这里插入图片描述
    内存中是这样的
    在这里插入图片描述
    实现深度克隆
    其实也就是再我们重写clone()方法时,进行手动的克隆再返回。

    package 原型模式;
    
    import java.util.List;
    //第一步实现Cloneable接口
    public class Student1 implements Cloneable{
    	private String[] arr = new String[2];
    	public String[] getArr() {
    		return arr;
    	}
    	public void setArr(String[] arr) {
    		this.arr = arr;
    	}
    	//	重写Object中的clone()方法
    	@Override
    	protected Student1 clone() throws CloneNotSupportedException {
    //		-------------------------实现深度克隆-----------------------
    //		先拿到克隆对象
    		Student1 student =(Student1)super.clone();
    //		然后进行手动克隆,自己进行循环赋值
    		
    //		先定义一个数组接受
    		String[] arr = new String[this.getArr().length];
    //		对拷
    		for(int i = 0; i < arr.length; i++) {
    			arr[i] = this.getArr()[i];
    		}
    		student.setArr(arr);
    		
    		return student;
    //		---------------------------------------------------------
    	}	
    }
    
    package 原型模式;
    import java.util.ArrayList;
    import java.util.List;
    public class Test {
    public static void main(String[] args) {
    	Student1 s1 = new Student1();
    	String[] arr = new String[2];
    	arr[0]="数组";
    	arr[1]="数据";
    	s1.setArr(arr);
    	System.out.println("s1地址:"+s1);
    	System.out.println("s1数组地址:"+s1.getArr());
    	System.out.println("存储信息:"+s1.getArr()[0]+"、"+s1.getArr()[1]);
    	
    	System.out.println("---------------------------------------------");
    	
    	try {
    		Student1 s2 = s1.clone();
    		System.out.println("s2地址:"+s2);
    		System.out.println("s2-集合地址:"+s2.getArr());
    		System.out.println("存储信息:"+s2.getArr()[0]+"、"+s2.getArr()[1]);
    	} catch (CloneNotSupportedException e) {
    		e.printStackTrace();
    	}
    	
    }
    }
    

    在这里插入图片描述

    原型模式的优缺点

    (一)、原型模式的优点

    1. 由于clone方法是有虚拟机直接复制内存块执行,所以在速度上比使用new的方式创建对象要快。
    2. 当创建的对象实例较为复杂的时候,使用原型模式可以简化对象创建的过程。
    3. 可以在运行时动态的获取对象的类型以及状态,从而创建一个对象

    (二)、原型模式的缺点

    1. 需要为每个类配备一个克隆方法,而且该克隆方法位于这个类里面,当对已有的类进行改造时需要修改源代码,违背了开比原则
    2. 在实现深度克隆的时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用的时候,为了实现深度克隆,每一层对象的类都必须支持深度克隆,实现起来比较麻烦!
  • 相关阅读:
    JavaScript之作用域和闭包
    mui.openWindow的html5+和web传参的兼容
    HTML5地理定位-Geolocation API
    wepy 编译警告去除办法
    Angular网络请求的封装
    网页资源加载的优化方法
    小DEMO之manifest初体验
    HDU 2846 Repository (字典树 后缀建树)
    mongodb适用和不适用的应用场景
    Codeforces 240E. Road Repairs 最小树形图+输出路径
  • 原文地址:https://www.cnblogs.com/geq2020/p/12687801.html
Copyright © 2020-2023  润新知