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;
    }
    
}

 

概念图:

 

测试类:

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;
    }
    
}

 

概念图:

 

测试类:

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

 

 

谢谢声明出处!

转自: http://www.cnblogs.com/gscq073240/articles/7122287.html

 

转载于:https://www.cnblogs.com/gscq073240/articles/7122287.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值