• 原型模式


    原型模式:

      通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

       java中的克隆技术,以某个对象为原型,复制出新的对象。新的对象具有原型对象的特性。

         优势有:效率高(直接克隆、避免了重新执行构造过程步骤)

      克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性

      值完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象(深克隆不会,浅克隆可能会)。然后,在修改克隆对象的值。

    原型模式实现:

      Cloneable接口的clone方法

      Prototype模式中实现起来最困难的地方就是内存的复制操作,所幸在Java中为我们提供了clone()方法

      替我们做了绝大部分事情。

    java提供了对于克隆的支持,想要实现克隆,必须实现Cloneable接口,该接口是个空接口,里面没有方法,此外还需要重写Object类的本地clone()方法。Cloneable接口的代码如下:

     

    /*
     * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     */
    package java.lang;
    /**
     * A class implements the <code>Cloneable</code> interface to
     * indicate to the {@link java.lang.Object#clone()} method that it
     * is legal for that method to make a
     * field-for-field copy of instances of that class.
     * <p>
     * Invoking Object's clone method on an instance that does not implement the
     * <code>Cloneable</code> interface results in the exception
     * <code>CloneNotSupportedException</code> being thrown.
     * <p>
     * By convention, classes that implement this interface should override
     * <tt>Object.clone</tt> (which is protected) with a public method.
     * See {@link java.lang.Object#clone()} for details on overriding this
     * method.
     * <p>
     * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
     * Therefore, it is not possible to clone an object merely by virtue of the
     * fact that it implements this interface.  Even if the clone method is invoked
     * reflectively, there is no guarantee that it will succeed.
     *
     * @author  unascribed
     * @see     java.lang.CloneNotSupportedException
     * @see     java.lang.Object#clone()
     * @since   JDK1.0
     */
    public interface Cloneable {
    }
    

      一个克隆的实现:

    package com.oj;
    
    import java.util.Date;
    
    /**
     * @author We.lxk
     *
     */
    public class Sheep implements Cloneable{
    	private String sname;
    	private Date date;
    	
    	public Sheep() {
    		// TODO Auto-generated constructor stub
    	}
    	
    	public Sheep(String sname, Date date) {
    		super();
    		this.sname = sname;
    		this.date = date;
    	}
    
    	public String getSname() {
    		return sname;
    	}
    
    
    	public void setSname(String sname) {
    		this.sname = sname;
    	}
    
    
    	public Date getDate() {
    		return date;
    	}
    
    
    	public void setDate(Date date) {
    		this.date = date;
    	}
    
    
    	@Override
    	protected Object clone() throws CloneNotSupportedException {
    		Object obj = super.clone();		//直接调用object对象的clone()方法
    		return obj;
    	}
    }
    

     测试代码:

    package com.oj;
    
    import java.util.Date;
    
    public class Client {
    	public static void main(String[] args) throws Exception {
    		Date d = new Date(123123123123123L);
    		Sheep s = new Sheep("少利",d);
    		System.out.println(s);
    		
    		
    		Sheep s2 = (Sheep) s.clone();
    		System.out.println(s2);
    		
    		System.out.println(s==s2);
    		
    		Sheep s3 = s;
    		System.out.println(s==s3);
    		
    		s2.setSname("呵呵");
    		System.out.println("s: "+s.getSname()+" , "+s.getDate()+"    s2: "+s2.getSname()+" , "+s2.getDate());
    		d.setTime(123123123123L);
    		System.out.println("s: "+s.getSname()+" , "+s.getDate()+"    s2: "+s2.getSname()+" , "+s2.getDate());
    	}
    }
    

     测试输出:

    com.oj.Sheep@16bd8ea
    com.oj.Sheep@16e1fb1
    false
    true
    s: 少利 , Mon Aug 14 11:32:03 CST 5871 s2: 呵呵 , Mon Aug 14 11:32:03 CST 5871
    s: 少利 , Mon Nov 26 08:52:03 CST 1973 s2: 呵呵 , Mon Nov 26 08:52:03 CST 1973

    通过输出可以发现,这个实现是浅克隆,s2克隆了s,克隆时只是把s中属性的值(引用类型,指向了一个地址)在堆中另外复制了一份,即把地址复制了一份,所以这个时候s和s2指向了堆中不同的位置,运用==比较时才会false,因为地址不一样了,这个地址所存储的值并没有复制,其中的Date d;仍然等于说是两个对象共用了一份,因此当你直接改变d的值得时候表现为s和s2两个输出的日期同时发生了变化,当你采用s.setDate(new Date(123L))时,这是在堆中新建立了一个Date对象,相当于同d已经脱离了,这是d已经只有s2中的date指向,s中的date指向了这个在堆中新建立的对象了,这时两者才算是脱离了;把s2直接赋值给s3时,两个地址引用指向了同一个堆中对象的位置,这个比较是相等的。

    下面进行深克隆

    package com.oj;
    
    import java.util.Date;
    
    /**
     * @author We.lxk
     *
     */
    public class Sheep2 implements Cloneable{
    	private String sname;
    	private Date date;
    	
    	public Sheep2() {
    		// TODO Auto-generated constructor stub
    	}
    	
    	public Sheep2(String sname, Date date) {
    		super();
    		this.sname = sname;
    		this.date = date;
    	}
    
    	public String getSname() {
    		return sname;
    	}
    
    
    	public void setSname(String sname) {
    		this.sname = sname;
    	}
    
    
    	public Date getDate() {
    		return date;
    	}
    
    
    	public void setDate(Date date) {
    		this.date = date;
    	}
    
    
    	@Override
    	protected Object clone() throws CloneNotSupportedException {
    		Object obj = super.clone();		//直接调用object对象的clone()方法
    		Sheep2 s = (Sheep2) obj;
    		s.date = (Date) this.date.clone();
    		return obj;
    	}
    }
    

     测试

    package com.oj;
    
    import java.util.Date;
    
    public class Client2 {
    	public static void main(String[] args) throws Exception {
    		Date d = new Date(123123123123123L);
    		Sheep2 s = new Sheep2("少利",d);
    		System.out.println(s);
    		
    		
    		Sheep2 s2 = (Sheep2) s.clone();
    		System.out.println(s2);
    		
    		System.out.println(s==s2);
    		
    		Sheep2 s3 = s;
    		System.out.println(s==s3);
    		
    		s2.setSname("呵呵");
    		System.out.println("s: "+s.getSname()+" , "+s.getDate()+"    s2: "+s2.getSname()+" , "+s2.getDate());
    		d.setTime(123123L);
    		System.out.println("s: "+s.getSname()+" , "+s.getDate()+"    s2: "+s2.getSname()+" , "+s2.getDate());
    		s2.setDate(new Date(123123123123L));
    		System.out.println("s: "+s.getSname()+" , "+s.getDate()+"    s2: "+s2.getSname()+" , "+s2.getDate());
    	}
    }
    

      输出:

    com.oj.Sheep2@16bd8ea
    com.oj.Sheep2@16e1fb1
    false
    true
    s: 少利 , Mon Aug 14 11:32:03 CST 5871 s2: 呵呵 , Mon Aug 14 11:32:03 CST 5871
    s: 少利 , Thu Jan 01 08:02:03 CST 1970 s2: 呵呵 , Mon Aug 14 11:32:03 CST 5871
    s: 少利 , Thu Jan 01 08:02:03 CST 1970 s2: 呵呵 , Mon Nov 26 08:52:03 CST 1973

    此时,已经完全将s里的date和s2的date完全分离了,因为在克隆代码里连同date对象一同进行了克隆。输出请遵循上述方法分析理解。

    端:

    态度决定高度,细节决定成败,
  • 相关阅读:
    租户功能
    async await
    IOptions and context
    Setting Management: 用于持久化设置Setting值
    设置模块
    vs2017单元测试没反应,检测出错误,有关详细信息,请查看“测试输出”窗口
    自定义JS组件+调用restfui接口显示(SpringBoot)
    flex布局采用justify-content:space-between时,当为两个内容时中间被空出的解决方案
    CSS3 边框彩虹跑马灯
    react native 调试时,调出DEV菜单
  • 原文地址:https://www.cnblogs.com/lxk2010012997/p/5290890.html
Copyright © 2020-2023  润新知