我们都知道对象序列化的目的是为了对象能够在网络上传输,以便存储对象,这是很有用处的,比如一个在线Flash游戏,玩家玩到一半想明天再玩,这时需要通过对象序列化把游戏数据保存起来,不然关闭浏览器数据就都没了,又要从头开始,当然利用Flash中的LSO也可以进行存储数据,不过是存在客户端上,这样的数据不一定能持久,对象序列化的主要目的是保存到服务器的数据库里,也许有人会问,干嘛不把对象的属性直接保存到数据库,还这么麻烦饶一大圈,这当然可以,但是如果对象的属性非常多,写起来会不会很繁琐呢,不如直接把对象保存起来这样反而跟简便,对象序列化的原理是把对象转换为字符串的形式,因为字符串任何语言都认识都能处理,而对象类型只能是属于特定的语言,比如一个Rectangle实例有width,height,fillColor,lineColor属性,把它转换为字符串格式后:"width=value|height=value|fillColor=value|lineColor=value"。
ActionScript 3本身并没有提供对象序列化的APIs,因为它已经有了flash remoting(AMF协议),AMF协议完成对象的序列化和反序列化,这里我们先不谈AMF,看看如何自定义实现对象的序列化,OReilly.Essential.ActionScript.3.0的作者提供了一系列类和接口来实现对象序列化,我们看看他是如何做的:
定义了一个 Serializable接口,只声明一个方法用于对象的序列化:
定义一个 实现 Serializable接口的 Serializer类,用于完成对象
一个继承 Serializer的Point类,我们将对Point类实例进行序列化处理:
测试类,输出结果为: y=6,x=5
我们看到已经成功把Point对象变成字符串“y=6,x=5”,我们再来看一个例子:
Shape类,定义了两个属性fillColor,lineColor:
Rectangle类继承Shape,同时实现 Serializable接口:
一个类要想能够被序列化,要么实现 Serializable接口,要么继承已经实现 Serializable接口的类,因为Rectangle类的父类没有实现 Serializable接口,所以Rectangle类必须实现 Serializable接口,而上面那个Point类的父类已经实现 Serializable接口,等于是间接实现了,我们看到Rectangle类的serialize()方法,把Serializer当作序列化工具,对Rectangle对象进行序列化处理, 对于核心类Serializer作者设计的比较巧妙,能同时处理两种情况的序列化。
最后还是要说一下一个小问题,假如序列化后的字符串保存到数据库了,再读取进行反序列化时,该怎么知道这些字符串是什么类的呢??? 我的想法是在序列化时同时保存类名以便为反序列化做准备,拿Point例子来说:
增加一个属性代表类名:
ActionScript 3本身并没有提供对象序列化的APIs,因为它已经有了flash remoting(AMF协议),AMF协议完成对象的序列化和反序列化,这里我们先不谈AMF,看看如何自定义实现对象的序列化,OReilly.Essential.ActionScript.3.0的作者提供了一系列类和接口来实现对象序列化,我们看看他是如何做的:
定义了一个 Serializable接口,只声明一个方法用于对象的序列化:
package
serializer
{
public interface Serializable
{
function serialize():String;
}
}
{
public interface Serializable
{
function serialize():String;
}
}
定义一个 实现 Serializable接口的 Serializer类,用于完成对象
package
serializer
{
public class Serializer implements Serializable
{
private var serializationVars:Array; //存储对象的属性
private var serializationObj:Serializable; //指向可序列化的对象引用
private var recordSeparator:String; //指定属性之间的分隔符
public function Serializer(){
setSerializationObj(this);
}
public function setSerializationVars(vars:Array):void{
serializationVars = vars;
}
public function setSerializationObj(obj:Serializable):void{
serializationObj = obj;
}
public function setRecordSeparator(rs:String):void{
recordSeparator = rs;
}
public function serialize():String
{
var s:String = "";
for (var i:int = serializationVars.length; --i >= 0;){
s += serializationVars[i] + "=" + String(serializationObj[serializationVars[i]]);
if(i>0){
s += recordSeparator;
}
}
return s;
}
}
}
{
public class Serializer implements Serializable
{
private var serializationVars:Array; //存储对象的属性
private var serializationObj:Serializable; //指向可序列化的对象引用
private var recordSeparator:String; //指定属性之间的分隔符
public function Serializer(){
setSerializationObj(this);
}
public function setSerializationVars(vars:Array):void{
serializationVars = vars;
}
public function setSerializationObj(obj:Serializable):void{
serializationObj = obj;
}
public function setRecordSeparator(rs:String):void{
recordSeparator = rs;
}
public function serialize():String
{
var s:String = "";
for (var i:int = serializationVars.length; --i >= 0;){
s += serializationVars[i] + "=" + String(serializationObj[serializationVars[i]]);
if(i>0){
s += recordSeparator;
}
}
return s;
}
}
}
一个继承 Serializer的Point类,我们将对Point类实例进行序列化处理:
package
serializer
{
public class Point extends Serializer
{
public var x:Number;
public var y:Number;
public var name:String = "Point";
public function Point(x:Number,y:Number)
{
super();
setRecordSeparator(","); //设置分隔符
setSerializationVars(["x","y"]); //序列化x,y属性
this.x = x;
this.y = y;
}
}
}
{
public class Point extends Serializer
{
public var x:Number;
public var y:Number;
public var name:String = "Point";
public function Point(x:Number,y:Number)
{
super();
setRecordSeparator(","); //设置分隔符
setSerializationVars(["x","y"]); //序列化x,y属性
this.x = x;
this.y = y;
}
}
}
测试类,输出结果为: y=6,x=5
package
{
import flash.display.Sprite;
import serializer.Point;
import serializer.Rectangle;
import serializer.Rectangle;
public class TestSerialization extends Sprite
{
public function TestSerialization()
{
super();
var p:Point = new Point(5,6);
trace(p.serialize());
}
}
}
{
import flash.display.Sprite;
import serializer.Point;
import serializer.Rectangle;
import serializer.Rectangle;
public class TestSerialization extends Sprite
{
public function TestSerialization()
{
super();
var p:Point = new Point(5,6);
trace(p.serialize());
}
}
}
我们看到已经成功把Point对象变成字符串“y=6,x=5”,我们再来看一个例子:
Shape类,定义了两个属性fillColor,lineColor:
package
serializer
{
public class Shape
{
public var fillColor:uint = 0xFFFFFF;
public var lineColor:uint = 0;
public function Shape(fillColor:uint,lineColor:uint){
this.fillColor = fillColor;
this.lineColor = lineColor;
}
}
}
{
public class Shape
{
public var fillColor:uint = 0xFFFFFF;
public var lineColor:uint = 0;
public function Shape(fillColor:uint,lineColor:uint){
this.fillColor = fillColor;
this.lineColor = lineColor;
}
}
}
Rectangle类继承Shape,同时实现 Serializable接口:
package
serializer
{
public class Rectangle extends Shape implements Serializable
{
public var width:Number = 0;
public var height:Number = 0;
public function Rectangle(fillColor:uint, lineColor:uint)
{
super(fillColor, lineColor);
}
public function setSize(w:Number,h:Number):void{
width = w;
height = h;
}
public function getArea():Number{
return width*height;
}
public function serialize():String
{
var ser:Serializer = new Serializer();
ser.setRecordSeparator("|");
ser.setSerializationVars(["height","width","fillColor","lineColor"]);
ser.setSerializationObj(this);
return ser.serialize();
}
}
}
{
public class Rectangle extends Shape implements Serializable
{
public var width:Number = 0;
public var height:Number = 0;
public function Rectangle(fillColor:uint, lineColor:uint)
{
super(fillColor, lineColor);
}
public function setSize(w:Number,h:Number):void{
width = w;
height = h;
}
public function getArea():Number{
return width*height;
}
public function serialize():String
{
var ser:Serializer = new Serializer();
ser.setRecordSeparator("|");
ser.setSerializationVars(["height","width","fillColor","lineColor"]);
ser.setSerializationObj(this);
return ser.serialize();
}
}
}
一个类要想能够被序列化,要么实现 Serializable接口,要么继承已经实现 Serializable接口的类,因为Rectangle类的父类没有实现 Serializable接口,所以Rectangle类必须实现 Serializable接口,而上面那个Point类的父类已经实现 Serializable接口,等于是间接实现了,我们看到Rectangle类的serialize()方法,把Serializer当作序列化工具,对Rectangle对象进行序列化处理, 对于核心类Serializer作者设计的比较巧妙,能同时处理两种情况的序列化。
最后还是要说一下一个小问题,假如序列化后的字符串保存到数据库了,再读取进行反序列化时,该怎么知道这些字符串是什么类的呢??? 我的想法是在序列化时同时保存类名以便为反序列化做准备,拿Point例子来说:
增加一个属性代表类名:
package
serializer
{
public class Point extends Serializer
{
public var x:Number;
public var y:Number;
public var name:String = "Point";
public function Point(x:Number,y:Number)
{
super();
setRecordSeparator(",");
setSerializationVars(["x","y","name"]);
this.x = x;
this.y = y;
}
}
}
{
public class Point extends Serializer
{
public var x:Number;
public var y:Number;
public var name:String = "Point";
public function Point(x:Number,y:Number)
{
super();
setRecordSeparator(",");
setSerializationVars(["x","y","name"]);
this.x = x;
this.y = y;
}
}
}