设计模式学习笔记(原型模式)
2011-11-23 20:28
239 查看
转载自: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游戏,英雄类含有两个成员变量:一个是英雄名字,为普通成员变量;一个是英雄属性,为引用成员变量(封装了英雄的状态,如生命值、魔法值)。为了实现对象实时拷贝的高效率,我们选择将对象序列化到内存(不是文件(硬盘))。通过输入输出流实现对象的“深拷贝”。
具体的实现代码如下:
package com.csufox.Prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
class Property implements java.io.Serializable{
int blood
= 100; //生命值
int magic
= 100; //魔法值
}
class Hero implements java.io.Serializable{ //需要实现序列化接口
String name = "英雄";
Property property = new Property(); //含有引用成员,需要“深”拷贝
public Hero
clone(){
Hero copy = null;
try{
//实例化ObjectOutputStream,写入字节数组输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
byte[]
data = baos .toByteArray(); //data是字节数组,存储着对象的拷贝
//实例化ObjectInputStream,从字节数组输入流中读取对象
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais);
copy = (Hero)ois.readObject();
}catch(Exception
ex){ex.printStackTrace();}
return copy;
}
}
public class Prototype
{
public static void main(String[]
args) throws Exception
{
Hero hero = new Hero();
hero.property.blood -= 20; //原英雄状态发生改变,生命值减少20
Hero copy = hero.clone();
System.out.println(copy.property.blood); //输出“80”,说明实现了实时拷贝和深拷贝
}
}
由上述代码可知,原型模式具有以下特点:
实现Serializable序列化接口;
在类中重写clone()方法(由Object继承而来);
通过Java I/0,将对象写入内存,然后再从内存读取(反序列化)。
原型模式(Prototype)属于创建型模式,实现了对象的创建;具体而言,它实现了对象的复制(拷贝)。
关于对象的复制,我们需要考虑以下两个问题:
1.对象实时状态的复制;
2.对象引用成员变量的复制。
如果通过new方式来实例化对象,只能得到对象的初始状态,这显然不行。在Java中,所有类都继承于Object类,而Object有一个clone()方法。通过查看JDK文档,该clone()方法虽然能够实现实时状态的复制(解决了问题1),但是只能实现“浅拷贝”,即只能实现基本数据类型(包含String)的拷贝,不能实现引用数据类型的拷贝,并不能满足原型模式的要求(问题2不能得到解决)。
怎么办?重写类的clone()方法,通过对象的写入写出来实现“深拷贝”和实时状态复制。重写(Override)需要遵循的条件是:方法名,参数列表和父类一致;返回值是父类返回值的子类。重写clone方法完全满足了条件。(无参数,方法名一致,返回的所有类都是Object的子类;当然可以不重写,方法名改用其它,但是不建议。)
可以想象,若一个类含有若干个引用数据类型(类),而该引用数据类型(类)中又含有若干个引用数据类型…这样嵌套下去,需要复制的就不是一个类,而是一个“类树”(树结构)。Java通过将对象序列化到文件或内存,底层封装了对类树的遍历和复制过程。这个机制已经封装,我们无需了解。
考虑这样一个应用场景:
一个RPG游戏,英雄类含有两个成员变量:一个是英雄名字,为普通成员变量;一个是英雄属性,为引用成员变量(封装了英雄的状态,如生命值、魔法值)。为了实现对象实时拷贝的高效率,我们选择将对象序列化到内存(不是文件(硬盘))。通过输入输出流实现对象的“深拷贝”。
具体的实现代码如下:
package com.csufox.Prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
class Property implements java.io.Serializable{
int blood
= 100; //生命值
int magic
= 100; //魔法值
}
class Hero implements java.io.Serializable{ //需要实现序列化接口
String name = "英雄";
Property property = new Property(); //含有引用成员,需要“深”拷贝
public Hero
clone(){
Hero copy = null;
try{
//实例化ObjectOutputStream,写入字节数组输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
byte[]
data = baos .toByteArray(); //data是字节数组,存储着对象的拷贝
//实例化ObjectInputStream,从字节数组输入流中读取对象
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais);
copy = (Hero)ois.readObject();
}catch(Exception
ex){ex.printStackTrace();}
return copy;
}
}
public class Prototype
{
public static void main(String[]
args) throws Exception
{
Hero hero = new Hero();
hero.property.blood -= 20; //原英雄状态发生改变,生命值减少20
Hero copy = hero.clone();
System.out.println(copy.property.blood); //输出“80”,说明实现了实时拷贝和深拷贝
}
}
由上述代码可知,原型模式具有以下特点:
实现Serializable序列化接口;
在类中重写clone()方法(由Object继承而来);
通过Java I/0,将对象写入内存,然后再从内存读取(反序列化)。
相关文章推荐
- 设计模式学习笔记——原型模式
- .Net设计模式学习笔记(六):原型模式(Prototype Pattern)
- 设计模式学习笔记--Prototype原型模式
- 设计模式学习笔记九:原型模式(和深浅复制)
- 设计模式学习笔记——原型模式
- java设计模式学习笔记--原型模式(浅克隆和深克隆)
- 学习笔记——JAVA设计模式<4>原型模式
- 设计模式学习笔记--原型模式
- C++设计模式学习笔记六:原型模式
- 设计模式学习笔记---原型模式prototype(Java版)
- 设计模式学习笔记九:原型模式(和深浅复制)
- 设计模式学习笔记-原型模式
- 阿Sam的设计模式学习笔记---- 原型(Prototype)模式
- 设计模式学习笔记——Prototype原型模式
- 设计模式学习笔记——Prototype原型模式
- 设计模式学习笔记(六)——Prototype原型模式
- 设计模式学习笔记九:原型模式(Prototype Pattern)
- java学习笔记-设计模式6(原型模式)
- 设计模式学习笔记(十一)—Prototype原型模式
- 步步为营 .NET 设计模式学习笔记 五、Prototype(原型模式)