Flyweight (享元)模式,是结构型模式,它是运用共享技术有效的支持大量细粒度的对象。
避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类),Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度。
适用性:
1、一个应用用了大量的对象,造成很大的存储开销。
2、对象的大多数状态可以改变为外部状态
3、如果删除对象的外部状态,那么可以用相对较少的共享对象爱那个取代很多组对象
4、应用程序不依赖于对象标识。
例子:网上有很多的关于FlyWeight的例子,我这里举个例子,是在flash中能说明问题的。
有这么一个需求,在一个flash界面需要大量的显示 人物的虚拟信息,可能显示到上千个。这个人物信息你很简单,头像(男人、女人来表示性别)、名字、年龄、省份。假设,Flash cs 已经导入两张图片 分别对应的类为 MalePic FemalePic。
你可能这样定义人物类
Character.as
package {
import flash.display.*;
import flash.text.*;
public class Character extends Sprite {
private var nameStr:String;
private var isMale:Boolean;
private var age:uint;
private var province:String;
private var portrait:Bitmap;
private var nameLabel:TextField;
private var ageLabel:TextField;
private var provinceLabel:TextField
public function Character(name:String,isMale:Boolean,age:uint,province:String) {
cratePortrait();
cratenaMeLabel();
crateAgeLabel();
crateProvinceLabel();
setName(name);
setSex(isMale);
setAge(age);
setProvince(province);
}
private function cratePortrait():void {
portrait = new Bitmap();
addChild(portrait);
}
private function cratenaMeLabel():void {
nameLabel = new TextField();
nameLabel.autoSize = TextFieldAutoSize.LEFT;
addChild(nameLabel);
nameLabel.x = 139;
}
private function crateAgeLabel():void {
ageLabel = new TextField();
ageLabel.autoSize = TextFieldAutoSize.LEFT;
addChild(ageLabel);
ageLabel.x = 139;
ageLabel.y = 20;
}
private function crateProvinceLabel():void {
provinceLabel = new TextField();
provinceLabel.autoSize = TextFieldAutoSize.LEFT;
addChild(provinceLabel);
provinceLabel.x = 139;
provinceLabel.y = 40;
}
public function setName(name:String):void {
this.nameStr = name;
nameLabel.text = "姓名:"+name;
}
public function getName():String {
return nameStr;
}
public function setSex(isMale:Boolean):void {
isMale = isMale;
if(isMale) {
portrait.bitmapData = new MalePic(0,0);
}
else {
portrait.bitmapData = new FemalePic(0,0);
}
}
public function getSex():String {
return isMale?"男":"女";
}
public function setAge(value:uint):void {
age = value;
ageLabel.text = "年龄:"+value.toString();
}
public function getAge():uint {
return age;
}
public function setProvince(value:String):void {
province = value;
provinceLabel.text = "省份: "+value;
}
public function getProvince():String {
return province;
}
}
}
然后在时间轴上面简单的写一个循环的代码,
for(var i=0;i<500;i++) {
var a:Character = new Character("张一"+i,true,i,"江苏");
addChild(a);
a.x = a.y = Math.random()*stage.stageWidth;
}
就会发现创建过程很卡。才500个就卡成这样?,想一想,头像几乎是每一次创建一个都要new 一个BitmapData(),反正就那么2个,能不能共用呢呢,不要每次都重新new 一下,在大量的对象面前,这是很浪费的。
还好设计模式里面有一个叫做,FlyWeight的模式,享元。
下面就用FlyWeight模式看看会不会好点。
PortraitFlyweight .as
package {
import flash.display.*;
public class PortraitFlyweight {
private var isMale:Boolean;
public function PortraitFlyweight(isMale:Boolean) {
this.isMale = isMale;
}
public function getBitmapDataBySex():BitmapData {
if(isMale) {
return new MalePic(0,0);
}
else {
return new FemalePic(0,0);
}
}
}
}
FlyWeightFactory .as
package {
public class FlyWeightFactory {
private static var instance:FlyWeightFactory;
public function FlyWeightFactory (){
}
public static function getInstace():FlyWeightFactory {
if(!instance) {
instance = new FlyWeightFactory();
}
return instance;
}
private var PortraitFlyweightArry:Array = [];
public function getPortraitFlyweight(isMale:Boolean):PortraitFlyweight {
var result:PortraitFlyweight = PortraitFlyweightArry[String(isMale)] as PortraitFlyweight;
if(!result) {
result = PortraitFlyweightArry[String(isMale)] = new PortraitFlyweight(isMale);
}
return result;
}
}
}