广东网站建设科技,中国建筑在线网,wordpress 新窗口,网站tag标签功能实现原型模式
原型模式就是使用复制对象#xff0c;创建出新的对象#xff0c;并且不需要知道创建的细节#xff08;比如类的属性的赋值等等#xff09;。
基本使用#xff08;浅拷贝#xff09;
常见的就是使用Object的clone方法。需要让类实现Cloneable并重写clone方法创建出新的对象并且不需要知道创建的细节比如类的属性的赋值等等。
基本使用浅拷贝
常见的就是使用Object的clone方法。需要让类实现Cloneable并重写clone方法才能使用。
public class A implements Cloneable{private String code;private String name;public A(String code, String name) {this.code code;this.name name;}public void setCode(String code) {this.code code;}Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}public static void main(String[] args) throws CloneNotSupportedException {A a new A(00,name1);A a1 (A)a.clone();a1.setCode(01);A a2 (A)a.clone();a2.setCode(02);System.out.println(a.hashCode());System.out.println(a1.hashCode());System.out.println(a2.hashCode());}
}结果很明显三个对象是不一样的。
596512129
824318946
930990596深拷贝
上面那种方式是浅拷贝即只能拷贝A类中的基本数据类型和String。对于A类中如果还有其他引用类型浅拷贝是实现不了引用类型的拷贝的。 所以需要进行对A深拷贝B通常有两种方法重写Clone方法和序列化。
方法1、重写A的clone方法并在方法中对B进行拷贝当然B类中也要实现浅拷贝。
public class B implements Serializable,Cloneable{private String id;Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}public class A implements Serializable,Cloneable{private String code;private String name;private B b;public A(String code, String name, B b) {this.code code;this.name name;this.b b;}public void setCode(String code) {this.code code;}Overridepublic Object clone() throws CloneNotSupportedException {A a (A)super.clone();// 在A的clone方法中对A的B引用进行clonea.b (B)a.b.clone();return a;}public static void main(String[] args) throws CloneNotSupportedException {A a new A(00,name1,new B());A a1 (A)a.clone();a1.setCode(01);A a2 (A)a.clone();a2.setCode(02);System.out.println(a.b.hashCode());System.out.println(a1.b.hashCode());System.out.println(a2.b.hashCode());}
}执行结果
596512129
824318946
930990596看执行结果每个A实例的B引用都是不同的hashCode值说明A中的B也被拷贝了。 如果将A中clone方法中的a.b (B)a.b.clone();注释掉可以得到最终打印出来的三个结果就是一样的。
方法2、序列化
序列化前提A和B都要实现Serializable接口。 A和B的定义还是和方法1一样我们只重写A中的clone方法。
Overridepublic Object clone() throws CloneNotSupportedException {ByteArrayOutputStream bos null;ObjectOutputStream oos null;ByteArrayInputStream bis null;ObjectInputStream ois null;try {//序列化以对象的方式输出去bos new ByteArrayOutputStream();oos new ObjectOutputStream(bos);oos.writeObject(this);//反序列化再以对象的方式写回来所有的引用类型自然都会带上了bis new ByteArrayInputStream(bos.toByteArray());ois new ObjectInputStream(bis);A copyResult (A)ois.readObject();return copyResult;} catch (Exception e) {e.printStackTrace();}finally {try {bos.close();oos.close();bis.close();ois.close();} catch (IOException e) {e.printStackTrace();}}return null;}最终效果也是随着A的cloneA中的B引用也被clone出新的一份来了。 上面的这个序列化只是一种实现思路也可以用fastjson将A对象转成json字符串再反转成A返回去其实原理都是一样的。
实际应用场景
其实很好找只要找到哪些类实现了Cloneable接口大概率就是用到了所谓了原型模式。
比如Spring的Bean的创建我都都知道默认是单例模式那其实还可以知道Bean是多例的这个就用到了原型模式。