二十三种设计模式——原型模式

前页:设计模式总述


我们在编程的时候,常常遇见这种情况:大量相同的类进行初始化,需要用到大量的构造函数。最基本的例子:

while(count-- > 0){
    String a = new String("asd");
}

这就是最简单的String类的构造函数。当我们频繁创建该对象时,会耗费资源且较耗时,因此,字这种情况下,java给出了一种方法,我们可以实现cloneable接口,从而生成大量类似对象。这就是原型模式。

public class ResembleType implements Cloneable{ //实现Cloneable接口
	public ResembleType () {                    //本身类的构造函数
		System.out.println("这里是原型");
	}
        @override
	public Object clone()throws CloneNotSupportedException{ //具体实现克隆的方法
		System.out.println("这里是复制原型");
		return (ResembleType)super.clone();
	}
}

public class ProtoType {                        //主函数调用

	public static void main(String[] args) throws CloneNotSupportedException {
		ResembleType resembleType = new ResembleType();
		ResembleType resembleType2 = (ResembleType)resembleType.clone();
	}
}

初次看这个模型,挺懵的。再来看看Cloneable源码:

/**
 * 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 {
}

这个Cloneable接口什么都没有写,也就是说不用实现它要求实现的函数。但是,我们需要重写方法:

 protected native Object clone() throws CloneNotSupportedException;

在这里,Cloneable接口仅仅是个标记。 如果不重写clone方法,编译器抛错。

public class ResembleType implements Cloneable{
	private String name;
	private int age;
	public ResembleType(String name, int age){
		this.name = name;
		this.age = age;
	}
	public void show(){
		System.out.println(this.name + "   " + this.age);
	}
	@Override
	public Object clone()throws CloneNotSupportedException{
		return (ResembleType) super.clone();
	}
}

public class ProtoType {

	public static void main(String[] args) throws CloneNotSupportedException {
		ResembleType resembleType = new ResembleType("Jack", 11);
		ResembleType resembleType2 = (ResembleType)resembleType.clone();
		resembleType.show();
		resembleType2.show();
	}
}

我们逐步加难度,现在这个类里面有两个私有成员了。在调用show函数的时候,我们看结果,和我们想要的一样

这种方式和直接new一个构造函数有什么区别呢?

答案就是:这种方式不会调用类中的构造函数,因为clone方法的原理是从堆内存中以二进制流的方式进行拷贝,直接分配一块新内存。


我总是回避JVM的内容,因为一直没有时间去拜读《深入理解JAVA虚拟机》这本书,因此对JVM也一知半解。

但是这里涉及到一个深浅克隆的问题。这与C++的深浅拷贝有些类似:拷贝构造函数。这是之前C++语言的内容,可以看一下,语言总是相通的。

java中基本数据类型有:int,char,short,long,float,double

复合数据类型有:String,enum,数组,自定义类等

  • 在浅克隆中,创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  • 在深克隆中,创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

图在:深浅拷贝

因此,如果使用浅克隆,得到的结果可能不尽人意。因为它在改变值的时候会连被克隆的对象的值一起改变,那么怎么实现深克隆呢?

答案也很简单,重写clone方法。

public Object clone()throws CloneNotSupportedException{
		ResembleType resembleType = (ResembleType)super.clone();
		resembleType.setName(resembleType.getName());
		return resembleType;
		//return (ResembleType) super.clone();
	}
//注意,若是自定义类,getName()要引用.clone()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值