设计模式(六) : 创建型模式--原型模式

在说原型模式之前,我们先来看java里面的深复制和浅复制:

1. 浅复制:被复制的对象的所有变量都持有和原来对象的变量相同的值,而所有的对其他对象的引用都指向原来的对象。

2. 深复制:被复制对象的所有变量都含有与原来对象相同的值,除去那些引用其他变量的对象。那些引用其他对象的变量将指向被复制过来的新对象,而不是原来那些被引用的对象。深复制需要把要复制的对象的所有引用都复制一遍。

这两者的区别就是关于引用对象的处理,浅复制是不考虑引用对象,而深复制需要考虑引用对象的问题。

对java中的clone()方法我们有以下约定:

1. 对于任何的对象x, 都有x.clone()!=x

2. 对于任何的对象x, 都有x.clone().getClass() == x.getClass();

3. 对于任何的对象x, 都有x.clone().equals(x) = true

 

继承自java.lang.Object的clone方法是浅复制。

 

在深复制的过程中我们需要考虑深复制的深度问题,可能会出现循环引用的问题,所以对于深复制,我们一般是利用串行化来做深复制的:先把对象写到流里,再从流里读出来。

下面是一段示意性的代码:

package com.javadesignpattern.prototype;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestDeepClone implements Serializable{
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        File file = new File("out.ser");
        FileOutputStream fos = new FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject("test");
        oos.flush();
        
        FileInputStream fis = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(fis);
        System.out.println(ois.readObject());
        ois.close();
    }

}

下面看原型模式的结构,《java与模式》中给出两种原型模式,一种是简单形式的原型模式,一种是登记型的原型模式。

1. 简单形式的原型模式

 

示意性代码:

package com.javadesignpattern.prototype.simple;

public interface Prototype extends Cloneable {
	
	public Object clone();

}

  

package com.javadesignpattern.prototype.simple;

public class ConcretePrototype implements Prototype {

    
    public Object clone(){
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }        
    }

}
package com.javadesignpattern.prototype.simple;

public class Client {
    
    private Prototype prototype;
    
    public void operation(Prototype example){
        Prototype prototype = (Prototype)example.clone();
    }
    
    public static void main(String[] args){
        Prototype prototypeTest = new ConcretePrototype();
        Client clientInctance = new Client();
        clientInctance.operation(prototypeTest);
        System.out.println(clientInctance.prototype);
    }

}

2. 登记形式的原型模式

 

示意性代码如下:

1. Prototype和CPrototype类和上面的简单原型模式没什么区别。

package com.javadesignpattern.prototype.register;

import java.util.ArrayList;

public class PrototypeManager {
    
    private ArrayList object = new ArrayList();

    public Prototype get(int i) {
        return (Prototype)object.get(i);
    }

    public void set(Prototype objectp) {
        object.add(objectp);
    }
    
    public int getSize(){
        return object.size();
    }
    

}
package com.javadesignpattern.prototype.register;

public class Client {
    
    private PrototypeManager mgr;
    private Prototype prototype;
    
    public String registerPrototype(){
        prototype = new ConcretePrototype();
        mgr = new PrototypeManager();
        mgr.set((Prototype)prototype.clone());    
        if(mgr != null ){
            return "SUCCESS";
        }else{
            return "FAILED";
        }
    }
    
    public static void main(String[] args){
        Client client = new Client();
        System.out.println(client.registerPrototype() + "-------" + client.mgr.getSize());
    }

}

 

 

简单原型模式和登记类型的原型模式的比较:

1. 如果需要创建的原型对象的数目比较少并且比较固定的话,我们可以选择第一种简单类型的原型,这种情况下,原型对象由客户端持有。

2. 如果需要创建的原型对象不固定的话,可以选择第二种方式:登记类型的原型,这样的话原型对象交给manager类持有,客户端从原型类中解脱出来,在创建一个新的原型对象之前,客户端可以看Manager类中是不是已经有符合条件的对象,有的话,就直接从manager类中拿出来用,没有的话,客户端就自己再去复制一份。

 

 

posted @ 2014-06-01 12:45  Ruth/Christy  阅读(130)  评论(0编辑  收藏