As3 一些设计手法笔记
继承手法:
As3 是面向对象的语言,因此可以使用继承(extends)的手法扩展我们所需要的功能。例如扩展Sprite 类,MovieClip类, Loader 类,Bitmap类,EventDipacher类,Event类等等其他相关能够被继承的类。这样既保留原有的类,组合更多有效类完成程序上的需要。
下面让我们使用继承手法扩展EventDipacher类,为什么会选择这个类作为这次解析。在As3里面显示编程是As3核心重点部分,DisplayObject类是显示编程的基础类,然而有意思的是它继承DisplayObject的父类就是这个事件分派类。由于EventDipacher类具备事件分派的能力,当我们使用继承手段扩展这个类的时候,我们设计的类就拥有了事件分派这样能力。
通过dispatchEvent 分派事件和监听事件行为,我们就可以实现相应事件模型。
好,下面进行设计
- package
- {
- import flash.events.*;
- public class Myclass extends EventDipacher
- {
- public function Myclass()
- {
- }
- }
- }
通过继承的方法,我们可以扩展我们的类,如增加一些属性和方法,增强类的功能
自定义事件类型:
众所周知,As升级到3.0版本后,拥有像javascript 一样事件模型,可以使用回调函数。
在As3里面,Even类是As3的基础事件类,有了这个类,我们可以轻松使用继承的手法扩展我们所需要的事件类型。
例: AnimationEvent.as 类
- public class AnimationEvent extends Event
- {
- public static const COUNT:String="count"; //自定义事件属性
- function AnimationEvent((type:String,bubbles:Boolean=false,cancelable:Boolean=false)
- {
- super(type,false;false);
- }
- override public function clone( ):Event
- {
- return new AnimationEvent (AnimationEvent.COUNT);
- }
- }
自定义的事件当中,我们可以自定义参数和属性、方法来增强自定义事件的功能。
静态方法组合设计:
静态方法使用,你用过没有?在设计当中知道怎样设计吗?下面就来探讨一下,在探讨之前,我们做一个小问题,计算30度余弦值究竟是多少?我们首先想到的是使用数学类当中的Math里面所在的方法, Math.cos(30*Math.PI/180);这样就完成我们所问的问题。
是不是很简单呢?的确是一件很容易的事情,现在回过头来,把关注的焦点应用放在Math类静态方法的使用上,在顶级类当中Math类里面封装有很多静态方法,这样静态方法封装了一系列的计算应用。有了这些应用,我们可以轻松完成一些复杂的计算。现在让我们看看这种类如下:采用一系列的静态方法组合成一个类,完成一组的功能。
- Package{
- public class Math
- {
- public function Math(){throw new Error(“不能实例化”)}
- public static function cos(arg:Number):Numbe{}
- public static function sin(arg:Number):Number{}
- public static function tan(arg:Number):Number{}
- }
这种设计的手法,主要针对用于一些工具类的使用上。如我们可以封装一套处理字符串的组合方式来处理一些登陆验证。
使用复杂的数据类型
Object 与Dictionary ,Array 是一组非常好用,而且当你熟悉了以后,你会发现会喜欢上这复杂数据类型。有了这三种法宝,我们就可以用它管理对象。好,闲话不多说,看看下面的设计。
首先使用的是Object类,Object类是一个动态类,可以动态添加属性,同时Object类可以作为一个关联数组的存储数据。借用这个特性,组合一些类。
var data:Object=new Object();
data[“one”]=”小明”;
data[“two”]=”小花”;
data[“three”]=”小红”;
或者
var data:Object={one:”小明”,two:”小花”,three:”小红”};
使用Obejct类作为参数:
- function handler(args:Object):void
- {
- var mc:MovieClip=args.mc;
- var alpha:Number=args.alpha;
- var scaleX:Number=args.scaleX;
- var scaleY:Number=args.scaleY;
- mc.alpha=alpha;
- mc.scaleX= scaleX;
- mc.scaleY=scaleY;
- }
调用:
handler ({mc:mc,alpha:0.5,scaleX:0.5,scaleY:0.5});
这样设置了一个mc里面的属性值,通过上面函数就能实现透明度减半,缩放0.5倍比例。
使用Dictionary类记录值:
Dictionary 特点之一就是采用键和值的关系方式来说明存储数据。Dictionary和Object有相似的地方,不过也存在一点差别,使用的时候需要注意。
var data: Dictionary=new Dictionary(true);
data[“id”]=11;//也可以是数值
data[“name”]=”flex”;//可以是字符串
data[“title”]=new Book();//可以是一个对象
下面看看是如何使用Dictionary这种关联的数组。
- package
- {
- import flash.utils.Dictionary;
- import flash.display.DisplayObject;
- import flash.events.EventDispatcher
- public class Queue extends EventDispatcher
- {
- private var childrenTotal:int;//记录队列中的总元素数目
- private var data:Dictionary;//记录队列元素的动态数组
- public function Queue()
- {
- data=new Dictionary(true);//存储队列中的元素
- childrenTotal=0;//初始化默认队列数目为0
- 81
- }
- //添加队列元素
- public function addItem(child:DisplayObject):DisplayObject
- {
- var name:String=child.name;//创建一个临时名字
- data[name]=child;//用动态数组记录键和值
- childrenTotal++; //递增元素
- return child;
- }
- //删除队列中某一个元素
- public function removeItem(child:DisplayObject):DisplayObject
- {
- //通过键来搜索是否匹配 是就删除
- delete data[child.name];
- childrenTotal--;//删除了自然就减少
- return child;
- }
- //返回队列中的元素
- public function get numChildren():int
- {
- return childrenTotal;
- }
- //通过名字搜索元素
- public function getChildByName(name:String):DisplayObject
- {
- return data[name];
- }
- //返回队列中所在位置
- public function getChildIndex(child:DisplayObject):int
- {
- var index:int=0;
- for each( var o:DisplayObject in data)
- {
- index++;
- if(o==data[child.name])
- {
- break;
- }
- }
- return index;
- }
- }
- }
使用Array类作为管理对象:
Array是经常使用的数据结构,用它来做数据管理是一种常见的设计手法,例如通过循环复制出很多图片,采用数组来管理。这样的方式比较直观和简单。
var array:Array=new Array();
for(var i:int=0;i<10;i++)
{
var photo:Photo=new Photo();
array.push(photo);
}
如果我们拿取数组的某一个对象,只需要通过索引就可以如array[i]=? 这样就可以。
接口组合设计:
使用接口设计,是一种比较常见的手法,特点就是提取出公共的部分方法,下面举一个简单例子。产品类接口,产品接口简单设计为名字,价钱,描述等(还有其他生产日期)
声明一个产品接口。
- package
- {
- public interface IProduct
- {
- function get Price():Number;//获取价钱
- function set Price(value:Number):void;//设置价钱
- function set name(str:String):void;//设置产品名字
- function get name():String;//获取产品名字
- function set describe(str:String):void;//设置产品描述
- function get describe():String;//获取产品
- }
- }
- 通过一个基础类Product实现该Iproduct接口。
- package
- {
- public class Product implements IProduct
- {
- private var price:Number;
- private var productName:String;
- private var mydescribe:String;
- public function Product()
- {
- }
- public function get Price():Number
- {
- return price;
- }
- public function set Price(value:Number):void
- {
- price=value;
- }
- public function set name(productname:String):void
- {
- productName=productname;
- }
- public function get name():String
- {
- return productName;
- }
- public function set describe(str:String):void
- {
- mydescribe=str;
- }
- public function get describe():String
- {
- return mydescribe;
- }
- }
- }
这样当我们继承了这个产品基础类的时候,就能够创建多更多不同种的产品类型。
等等。
- package
- {
- public class ProductA extends Product
- {
- public function ProductA()
- {
- }
- }
- }
克隆对象设计
- package
- {
- import flash.display.Sprite;
- public class Photo extends Sprite
- {
- public function Photo()
- {
- }
- public function clone():Photo
- {
- return new Photo() ;
- }
- }
- }
实例化某一个对象的时候,我们通过new的方式来实现,但是如果我们不希望
var myphoto1:Photo=new Photo();
var myphoto2:Photo=new Photo();
var myphoto3:Photo=new Photo();
采用这样的方式创建实例,也可以使用下面这种
var myphoto1:Photo=new Photo();
var myphoto2:Photo= myphoto1.clone();
var myphoto3:Photo= myphoto1.clone();
这样就是一种克隆对象的一种设计手法,其原来就是递归返回一种和自带类相同的类型。
在设计模式当中的单例模式,就是使用这种递归的方式来创建对象。