天天看點

23模式之: 原型模式demo

淺克隆Demo:

羊:

package prototype_mode;

import java.util.Date;

/**
 * 羊
 * 對象要可以克隆, 需要實作空接口, 标記接口Cloneable, 這是規範
 * clone是object方法, c實作, 效率極高
 */
public class Sheep implements Cloneable {
    
    private String sname;
    private Date birthday;

    
    /**
     * 覆寫父類(Object)的克隆方法, 測試淺克隆
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接調用object對象的clone()方法進行克隆, 傳回克隆後的對象!
        return obj;
    }
    
    
    public Sheep(){
    }
    
    public Sheep(String sname, Date birthday) {
        this.sname = sname;
        this.birthday = birthday;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
}      

概念圖:

23模式之: 原型模式demo

測試類:

package prototype_mode;

import java.util.Date;

/**
 * 測試原型模式, 淺克隆
 */
public class Client {

    public static void main(String[] args) throws CloneNotSupportedException {
        //建立原型對象
        Sheep s1 = new Sheep("少利", new Date(12312312312l));
        System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
        
        //克隆原型對象
        Sheep s2 = (Sheep) s1.clone();
        System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
        
        //修改克隆對象
        s2.setSname("多利");    //1997年, 英國的克隆羊, 多利!
        s2.getBirthday().setTime(32132132132l);
        
        //列印兩個對象
        System.out.println("--------------------------------");
        System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
        System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
        
        
        //結果: 克隆對date對象隻是引用(值)克隆
    }
    
}      

列印結果:

prototype_mode.Sheep@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep@647e05: 少利, Sat May 23 20:05:12 CST 1970
--------------------------------
prototype_mode.Sheep@1db9742: 少利, Fri Jan 08 05:35:32 CST 1971
prototype_mode.Sheep@647e05: 多利, Fri Jan 08 05:35:32 CST 1971      

深克隆Demo:

羊2号:

package prototype_mode;

import java.util.Date;

/**
 * 羊2号
 */
public class Sheep2 implements Cloneable {    //1997年, 英國的克隆羊, 多利!
    
    private String sname;
    private Date birthday;

    
    /**
     * 覆寫父類(Object)的克隆方法, 測試深克隆
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();//直接調用object對象的clone()方法進行克隆, 傳回克隆後的對象!
        //需要對Date對象也進行克隆, 如果Date對象中擁有對象, 也要一層一層的全部克隆
        Sheep2 s = (Sheep2) obj;
        s.birthday = (Date) this.birthday.clone();//傳回克隆後的Date!
        return obj;
    }

    
    public Sheep2(){
    }
    
    
    public Sheep2(String sname, Date birthday) {
        this.sname = sname;
        this.birthday = birthday;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
}      
23模式之: 原型模式demo
package prototype_mode;

import java.util.Date;

/**
 * 測試原型模式, 深克隆
 */
public class Client2 {

    public static void main(String[] args) throws CloneNotSupportedException {
        //建立原型對象
        Sheep2 s1 = new Sheep2("少利", new Date(12312312312l));
        System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
        
        //克隆原型對象
        Sheep2 s2 = (Sheep2) s1.clone();
        System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
        
        //修改克隆對象
        s2.setSname("多利");    //1997年, 英國的克隆羊, 多利!
        s2.getBirthday().setTime(32132132132l);
        
        //列印兩個對象
        System.out.println("--------------------------------");
        System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
        System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
        
        
        //結果: 克隆對象時對Date也進行了克隆
    }
    
}      
prototype_mode.Sheep2@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep2@647e05: 少利, Sat May 23 20:05:12 CST 1970
--------------------------------
prototype_mode.Sheep2@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep2@647e05: 多利, Fri Jan 08 05:35:32 CST 1971      

以序列化形式深克隆Demo:

羊3号:

package prototype_mode;

import java.io.Serializable;
import java.util.Date;

/**
 * 羊3号
 * 序列化UID唯一辨別.
 * 反序列化時,如果UID不一緻,就無法實作反序列化,并且将抛出InvalidClassException.[方法,域不能減,可以增,向後相容]
 * 如果不顯式指定,VM預設生成一個(耗費資源),但反序列化時會出問題.
 */
public class Sheep3 implements Cloneable, Serializable {
    private static final long serialVersionUID = 1218060507823188744L;
    
    private String sname;
    private Date birthday;

    public Sheep3(){
    }
    
    public Sheep3(String sname, Date birthday) {
        this.sname = sname;
        this.birthday = birthday;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
}      
package prototype_mode;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

/**
 * 測試原型模式, 深克隆
 * 使用序列化和反序列化的方式實作深複制, 待複制對象需要實作Serializable接口
 */
public class Client3 {

    public static void main(String[] args) throws Exception {
        //建立原型對象
        Sheep3 s3 = new Sheep3("少利", new Date(12312312312l));
        System.out.println(s3 + ": " + s3.getSname() + ", " + s3.getBirthday());
        
        
        //使用序列化和反序列化實作深複制
        
        //位元組流形式
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);//建立object輸出流(傳入位元組數組輸出流)
        oos.writeObject(s3);//序列化羊, 包括所有持有對象也一并
        byte[] bytes = bos.toByteArray();//從位元組數組輸出流中, 獲得位元組數組
        oos.close();
        
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bis);//建立object輸入流(傳入位元組數組輸入流)
        Sheep3 ss3 = (Sheep3) ois.readObject();//反序列化羊
        ois.close();
        System.out.println(ss3 + ": " + ss3.getSname() + ", " + ss3.getBirthday());
        
        
        //檔案流形式
//        ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(new File("D:\\file1")));
//        oos2.writeObject(s3);
//        oos2.close();
//        
//        ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream(new File("D:\\file1")));
//        Sheep3 ss3 = (Sheep3) ois2.readObject();
//        ois2.close();
//        System.out.println(ss3 + ": " + ss3.getSname() + ", " + ss3.getBirthday());
        
        
        //修改複制對象
        ss3.setSname("多利");    //1997年, 英國的克隆羊, 多利!
        ss3.getBirthday().setTime(32132132132l);
        
        //列印兩個對象
        System.out.println("--------------------------------");
        System.out.println(s3 + ": " + s3.getSname() + ", " + s3.getBirthday());
        System.out.println(ss3 + ": " + ss3.getSname() + ", " + ss3.getBirthday());
        
        
        //結果: 序列化時, 對Date也進行了複制
    }
    
}      
prototype_mode.Sheep3@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep3@1311334: 少利, Sat May 23 20:05:12 CST 1970
--------------------------------
prototype_mode.Sheep3@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep3@1311334: 多利, Fri Jan 08 05:35:32 CST 1971