一日一摸之第二日:原型模式

 
所谓原型模式,就是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式不是利用类产生对象实例,而是从一个对象实例产生出另一个对象实例,复制建立对象。 命名由来是因为这个 Pattern 是根据被视为原型的对象实例,才能建立另一个新对象实例。
原型模式就是通过Java类的克隆方法实现的,这就要求每一个类都必须实现一个克隆方法,这对于全新的类来说并不是很难,而对于已经有的类就不大容易,应该在实现克隆方法时需要对类的功能进行通盘考虑,后面会提到浅克隆和深克隆的区别。特别是当一个类引用到不支持串行化serialize的节间对象,或者引用含有循环结构的时候。
实例如下(ProtoTypeSample.java JDK1.5测试通过):
import java.util.HashMap;
/**
 *原型接口
 */
interface Action extends Cloneable{
   public int execute();
   public Object createClone();
}
 
/**
 *具体原型类1
 */
class SubAction implements Action{
    private int firstParam;
    private int secondParam;
    public SubAction(int param1,int param2){
            System.out.println("create a subAction example");
        this.firstParam = param1;
         this.secondParam = param2;
     }
     public int execute(){
            return firstParam - secondParam;
     }
 
     public Object createClone(){
            Object o = null;
            try{
                   o = super.clone();
            }catch(Exception e){
            }
            return o;
     }
 
}
 
/**
 *具体原型类2
 */
class AddAction implements Action{
    private int firstParam;
    private int secondParam;
    public AddAction(int param1,int param2){
            System.out.println("Create a AddAction example");
        this.firstParam = param1;
         this.secondParam = param2;
     }
     public int execute(){
            return firstParam + secondParam;
     }
 
     public Object createClone(){
            Object o = null ;
            try{
                   o = super.clone();
            }catch(Exception e){
            }
            return o;
     }
 
}
 
/**
 *原型管理
 */
class ProtoTypeManager
{
     private static HashMap ptMap = new HashMap();
     public static void register(String name,Action action){
            ptMap.put(name,action);
     }
    
     public static Action unRegister(String name){
            return (Action)ptMap.remove(name);
     }
    
     public static Action createAction(String name){
//           return (Action)((Action)ptMap.get(name)).clone();
            return (Action)((Action)ptMap.get(name)).createClone();
     }
 
}
 
public class ProtoTypeSample{
    public static void main(String[] args){
            //被视为原型的实例
            Action sub = new SubAction(4,55);
            Action add = new AddAction(444,222);
            ProtoTypeManager.register("sub",sub);
            ProtoTypeManager.register("add",add);
            Action tmp = (Action)ProtoTypeManager.unRegister("sub");
            System.out.println(tmp.execute());
            Action ptCreator = ProtoTypeManager.createAction("add");
            System.out.println(ptCreator.execute());
     }
}
使用原型模式而不是使用new关键字的区别在于,当一个对象处在一个复杂状态时,如果希望得到一个拷贝,同时又具有这个对象一模一样的状态,如果使用new,将不得不重新一个一个地来设置这些状态,有时候比较麻烦,有时候很难做到,此时如果使用原型模式,就将会是一个很好的解决方法。
在Object中,clone方法所做的操作就是直接复制字段内容,并不管该字段对应的对象实例内容,如果是一个通过new方式生成的对象,当你使用这种clone方法进行复制时,复制的结果只对应该对象的引用而已。在重写clone方法时,一定要注意避免“浅拷贝”,务必要做到“深拷贝”。Clone只会进行复制,不会调用构造函数。
在一个类中如果只包含基本数据类型,object提供的clone方法就足够,如果是由其他对象合并而成的,为了对其进行深层复制,super.clone()的结果必须造成成当前的对象,并对其中的对象进行深度克隆。如下例
     class DeepObject implements Cloneable
     {
            CompiseObject obj1 = new CompiseObject();
            CompiseObject ojb2 = new CompiseObject();
            public Object clone(){
                   DeepObject o = null;
                   try{
                          o = (DeepObject)super.clone();
                   }catch(Exception e){
                   }
                   o.obj1 = (CompiseObject)o.obj1.clone();
                   o.obj2 = (CompiseObject)o.obj2.clone();
                   return 0;
            }
     }
如果对象中有Vector这样的成员,在克隆了Vector之后,必须在其中遍历,并克隆由Vector指向的每个对象,对于HashMap、Hashtable……也都必须采取类似的处理。
以前在对一个对象进行序列化以后再撤销对它的序列化,实际也就是一个克隆的过程。但序列化要比克隆要耗费多得多的时间,同时序列化技术的运行结果并不稳定,而克隆每一次花费的时间都是相同的。
在添加克隆能力之前,编译器会阻止我们的克隆尝试,一旦在层次结构中添加了克隆能力,那么当前添加的类以及它所有的子类都可以进行克隆.
Ref:
1、 Thinking In Java
2、 Java设计模式
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值