设计模式学习笔记(原型模式)

转载自:http://www.impeng.org/prototype.html

原型模式(Prototype)属于创建型模式,实现了对象的创建;具体而言,它实现了对象的复制(拷贝)。

关于对象的复制,我们需要考虑以下两个问题:

1.对象实时状态的复制;

2.对象引用成员变量的复制。

如果通过new方式来实例化对象,只能得到对象的初始状态,这显然不行。在Java中,所有类都继承于Object类,而Object有一个clone()方法。通过查看JDK文档,该clone()方法虽然能够实现实时状态的复制(解决了问题1),但是只能实现“浅拷贝”,即只能实现基本数据类型(包含String)的拷贝,不能实现引用数据类型的拷贝,并不能满足原型模式的要求(问题2不能得到解决)。

怎么办?重写类的clone()方法,通过对象的写入写出来实现“深拷贝”和实时状态复制。重写(Override)需要遵循的条件是:方法名,参数列表和父类一致;返回值是父类返回值的子类。重写clone方法完全满足了条件。(无参数,方法名一致,返回的所有类都是Object的子类;当然可以不重写,方法名改用其它,但是不建议。)

可以想象,若一个类含有若干个引用数据类型(类),而该引用数据类型(类)中又含有若干个引用数据类型…这样嵌套下去,需要复制的就不是一个类,而是一个“类树”(树结构)。Java通过将对象序列化到文件或内存,底层封装了对类树的遍历和复制过程。这个机制已经封装,我们无需了解。

考虑这样一个应用场景:

一个RPG游戏,英雄类含有两个成员变量:一个是英雄名字,为普通成员变量;一个是英雄属性,为引用成员变量(封装了英雄的状态,如生命值、魔法值)。为了实现对象实时拷贝的高效率,我们选择将对象序列化到内存(不是文件(硬盘))。通过输入输出流实现对象的“深拷贝”。

具体的实现代码如下:

  1. package com.csufox.Prototype;  
  2.  
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.ByteArrayOutputStream;  
  5. import java.io.ObjectInputStream;  
  6. import java.io.ObjectOutputStream;  
  7.  
  8. class Property implements java.io.Serializable{  
  9.     int blood = 100;  //生命值  
  10.     int magic = 100;  //魔法值  
  11. }  
  12.  
  13. class Hero implements java.io.Serializable{ //需要实现序列化接口  
  14.     String name = "英雄";  
  15.     Property property = new Property(); //含有引用成员,需要“深”拷贝  
  16.  
  17.     public Hero clone(){  
  18.         Hero copy = null;  
  19.         try{  
  20.             //实例化ObjectOutputStream,写入字节数组输出流  
  21.             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  22.             ObjectOutputStream oos = new ObjectOutputStream(baos);  
  23.             oos.writeObject(this);  
  24.             byte[] data = baos .toByteArray();  //data是字节数组,存储着对象的拷贝  
  25.             //实例化ObjectInputStream,从字节数组输入流中读取对象  
  26.             ByteArrayInputStream bais = new ByteArrayInputStream(data);  
  27.             ObjectInputStream ois = new ObjectInputStream(bais);  
  28.             copy = (Hero)ois.readObject();  
  29.         }catch(Exception ex){ex.printStackTrace();}  
  30.         return copy;  
  31.     }  
  32. }  
  33.  
  34. public class Prototype {  
  35.     public static void main(String[] args) throws Exception {  
  36.         Hero hero = new Hero();  
  37.         hero.property.blood -= 20;  //原英雄状态发生改变,生命值减少20  
  38.         Hero copy = hero.clone();  
  39.         System.out.println(copy.property.blood);  //输出“80”,说明实现了实时拷贝和深拷贝  
  40.     }  

由上述代码可知,原型模式具有以下特点:

  1. 实现Serializable序列化接口;
  2. 在类中重写clone()方法(由Object继承而来);
  3. 通过Java I/0,将对象写入内存,然后再从内存读取(反序列化)。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值