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

前页:设计模式总述


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

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 Cloneable 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.
 * 

* Invoking Object's clone method on an instance that does not implement the * Cloneable interface results in the exception * CloneNotSupportedException being thrown. *

* By convention, classes that implement this interface should override * Object.clone (which is protected) with a public method. * See {@link java.lang.Object#clone()} for details on overriding this * method. *

* Note that this interface does not contain the clone 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()

 

你可能感兴趣的:(设计模式,java)