prototype原型模式,详解java Clone

来源:互联网 发布:诺基亚java软件下载 编辑:程序博客网 时间:2024/06/16 04:23

定义;Prototype Pattern :Specify the kinds of objects to crete using a prototypical instance ,and crete new objects by copying this protype

 

(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象)

优点:Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。

 

类图。。。。非常简单 。。工具坏了, 就不给出了以后补上。例子同样简单不过感觉网上的很多例子都不能体现出原型模式的精髓。

jive 中的原型模式用的非常精髓,用在装饰器上, 因为论坛设定可以给代码加量,网址超链接,这个功能是通过 装饰器模式实现的。可是论坛访问量大了以后装饰器,可能在同一时刻被多次调用,所以使用原型模式,使用装饰器的副本做处理。

 

还有就是设计模式值禅中讲的也还算不错。 讲了一个大概是给客户发邮件的问题,如果单线程发那实在太慢了,多线程的时候就会发生并发的问题,当然有很多方法可以解决,比如加锁?做同步操作,但这样同样很费时。而我们可以使用原型模式,修改的是原型的副本 ,这样各个线程之间不会 相互影响。

 

 

主要我们还是来解析一下java 中的 clone 方法和 Cloneable 接口

 

给出例子 并给出深刻克隆与浅克隆 的例子

 

package com.meran.normalTest;import java.util.ArrayList;public class LightClone implements Cloneable{private ArrayList<String> list=new ArrayList<String>();public void setString(String s){list.add(s);};public void displayList(){for(String s : list)System.out.println(s);}     public static void main(String [] args){LightClone test=new LightClone();test.setString("a");  System.out.println("拷贝前");  test.displayList();try {LightClone clone=(LightClone)test.clone();clone.setString("b");System.out.println("拷贝后");test.displayList();} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


 

拷贝前a拷贝后ab


 

这个结果很有趣 ,克隆后的对象我们给其链表添加元素,打印被克隆对象链表的元素, 元素竟然也增加了。 这就是浅克隆机制,浅克隆的时候,只创建新对象,并把被克隆对象中

的非引用类型克隆,也就是说,只把被克隆对象中的基础类型和String 类型的变量克隆到新对象中,而引用对象只是传递给新对象中一个关于该引用对象的引用。

 

 

深拷贝,也就是什么都拷贝啦。就是完完全全的拷贝,这时需要重写 clone 方法,把需要拷贝的引用类型自己手动拷贝进去。

 

下面给一个例子

package com.meran.normalTest;import java.util.ArrayList;/* * 测试final关键字 */public class FinalTest implements Cloneable{     private final  ArrayList<Integer> finalList=new ArrayList<Integer>();     private ArrayList normalList=new ArrayList();      public void add(int i){     finalList.add(i);     }     public void addInt(int i){     normalList.add(i);     }     public void addString(String s){     normalList.add(s);     }     public void displayNormalList(){     for(int i=0;i<normalList.size();i++){     System.out.println((Integer)normalList.get(i)); //抛出转型异常     }     }     public void displayFinalList(){    for(int i:finalList){         System.out.println(i);    }     }     @Override     public FinalTest clone(){     FinalTest finalTest=null;     try {finalTest=(FinalTest)super.clone();//下面这句报错 因为它是final 型的//finalTest.finalList=(ArrayList<Integer>)this.finalList.clone();finalTest.normalList=(ArrayList)this.normalList.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return finalTest;          }     public static void main(String [] args){     FinalTest  test=new FinalTest();     test.add(2);     test.add(3);     test.displayFinalList();     test.addInt(1);     test.addString("sss");     test.displayNormalList();     //结果为 2, 3 此处看出 final 修饰引用类型,表示指向的引用不可改变     } }


被拷贝的引用类型不可以被final修饰,要么会被报错。

 

 

 

网上还有人写利用反射来实现深拷贝 原理比较简单,大家可以自己想想哈

 


 

 

原创粉丝点击