zoukankan      html  css  js  c++  java
  • 原型模式

    原型模式:

      通过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对象一同进行了克隆。输出请遵循上述方法分析理解。

    端:

    态度决定高度,细节决定成败,
  • 相关阅读:
    笔记35 跨重定向请求传递数
    判断邮箱的正则表达式
    按钮
    async await 的用法
    笔记34 Spring MVC的高级技术——处理multipart形式的数据
    Convert Sorted Array to Binary Search Tree
    Binary Tree Zigzag Level Order Traversal
    Unique Binary Search Trees,Unique Binary Search Trees II
    Validate Binary Search Tree
    Populating Next Right Pointers in Each Node,Populating Next Right Pointers in Each Node II
  • 原文地址:https://www.cnblogs.com/lxk2010012997/p/5290890.html
Copyright © 2011-2022 走看看