as3设计模式乱用之工厂模式

好久没写技术相关的日记了,一忙,二懒,三则被这单调的生活熏得没什么感悟。

其实这篇日记早就想写了,项目开发初期的时候,带学生。经常看到那种乱用设计模式的现象。一方面,公司面试人的时候喜欢问设计模式,另一方向设计模式相关的书夸大了设计模式。紧接着的就是一群刚入行的人盲目的崇拜和乱用,感觉用了设计模式就牛逼,用了就脱离菜鸟群体。

 

好吧,今天蛋痛。先声明,这篇文字纯个人感觉写,我不是博士也不是研究生,不保证观点全正确。

我用一个简单的程序员说法,工厂模式是一个类里面有个工厂,工厂通过switch把字符串转成新建的子对象。
as代码大概如下:

class factory
{
public function createItem(itemName:String):ItemBase
{
switch(itemName)
{
case...
}

}

  

详细的那几个类的网上随便搜,我就不粘贴了。

我想说的是这个模式给我们开发带来的好处有哪些。读过两本关卡设计模式的书,不知是巧合还是不负责的抄袭。两本书为说明工厂的好处都举了个打印机的例子。
按书上说,用工厂的好处是隐藏产品类。如果我需要创建一台打印机,我只需要创建工厂就行。其实这个说法非常别扭,换个说法我只需要打印,我干麻要非要多余找个工厂。尽信书不如无书啊,这摆明就是google翻译忽悠买书人啊。
o'reilly的书(as设计模式)还举了个飞机和子弹的例子。当年刚开始看的时候,是和两个刚出社会的同事一起的。有人表示,很灵活啊,我要创建子弹就从工厂里面创建。其实我那时就很纳闷,我直接new一个子弹就得了。搞个子弹基类,还得建立工厂,建好了还要从工厂里面通过字符串创建。码量多了好多,其结果就是出个子弹而已。这个飞机子弹的例子,我们加个另一个前提就更容易理解了,因为前后端交互,服务端给客户端的是字符串或者是整型,客户端要通过这个字符串转换成子弹显示在场景。如此就不得不用上工厂模式。不过话说回来,既然是不得不用,那书就算不看我们也一样是这样写代码,而看了书的人大多只会用switch。不看的还会用反射和映射。
谈到了这里我想起不只一次听过的话,"用模式,性能会下降些"。其实这句话是有问题的,很多情况下我们是不得不用模式。就如上面说的服务端字段转子弹的例子。所以跟本不存在用会下降不用提升的说法。硬要说会造成性能浪费的话,只能说是乱用,见下例。


这是个奇怪的例子,这串代码是要创建一个按钮显示到界面上。我读旧项目经常碰到这种写法,毕竟一个项目经过的人手多,什么风格都有。

var btn:RedButton = BtnFactory.createBtn(BtnName.RED) as RedButton;

  


开发者本来只需要一个红色的按钮,但是却弄了个工厂,在工厂里面通过switch来创建。这样做有什么好处?干麻不直接btn = new RedButton();我只能说,死读书害死人。上例这种写法我们也不能说他有错,但是不得不说,浪费这么多代码没换来什么好处。
如果说我们希望一个xml来配置显示产生不同的按钮,那工厂写法是有用的,因为配置文件全是字符串,我们需要字符串来创建不同的按钮。但是自己写的一个项目,并无任何配置的东西,这样硬生生加个工厂不就变成了浪费体力了吗。


搜了很多国外的资料,老外关于as3用是否合适用设计模式进行了不少口水战。而到了国内,就变成了尽信模式,省下了口水。首先我先表明一下自己的关点,本人认为如果追求快速开发,并且对代码严谨性没有强迫证的话,as3的很多设计模式都可以用反射替代。
说起反射这个词,是从java那学来的,详细的作用是通过类的字符串创建实例。在as里面实现比java简单得多。例如:

public function getBut(btnName:String="Button"):Button
{
var cls:Class = applicationDomain.getDefinition("Button") as Class;
return new cls();
}

  


这个写法也很简单和工厂一样,通过一个字符串来创建子项产品。但是为什么书上不说用反射工厂,却要搞好几个类来连接呢?其实这也是有原因的,因为早年,java刚开始的那几个版本是没有反射这个东西的。别说早年的java,现在的C要实现反射也是件麻烦的事。

举个常用的例子,例如我们要写个列表组件List。列表通过循环创建有子项,每个子项从上到下按Y抽进行排列。我写好了列表之后,给其他人用,别人当然就不希望再重新写一次子项创建和Y排列啦,但是他们要显示的子项是不一样的。相信开发过一个项目的人都知道,在列表里面用一个Class类型的变量存子项类型,循环创建子项可通过这个变量来创建子项。
大致代码如下:

var ls:List = new List();
ls.itemClass = OtherItem;
ls.data = [11,22,33];

  

在这里我提个假设,如果不用Class变量来反射的话,(也就是不准用Class类型的变量)。别人要用你写的List类,但又要产生不同的子项,要怎么办?
这种情况下我们可以写一个protected方法来创建子项,别人用的时候就新建一个List2和一个自己的MyItem,继承于List,然后覆盖掉那个protected方法来返回新子项MyItem。这个方法比较简单就不上码了,至于叫什么模式我不记得了,毕竟不是搞学术,唉。
还有另一种方法就是搞模式的人最喜欢用的,定一个工厂方法接口IItemFactory,这个接口有一个创建子项的方法,List里定一个接口变量。别人扩展的时候新建一个子项工厂接入那个IItemFactory,然后实现那个方法返回一个新的MyItem。(写完这段,发现自己表述水平真有限,算了,上码吧)。

//IItemFactory代码
class IItemFactory
{
function createItem():ItemBase;
}

//ItemFactory代码:
class ItemFactory implements IItemFactory
{
public function createItem():ItemBase
{
return new MyItem();
}
}


//List部份代码:
class List
{
...
public var itemFactory:IItemFactory;

for (var i:int = 0; i < data.length; i++) 
{
var itm:ItemBase = itemFactory.createItem();
...
addChild(itm);
}
}
//使用代码
var ls:List = new List();
var itmf:IItemFactory = new ItemFactory();
ls.itemFactory = itmf;
ls.data = [11,22,33];
...

  


怎么样,很复杂吧。这就是命贱不用反射,硬生生要用工厂的后果。呵呵~~

这两个例子算是把反射替代工厂好处说完了吧。下面想说一下严谨性这个东西。虽然我目前是搞as3的,但说句实话,as3的语法确实不如java严谨,java有一个叫做泛型的东西,泛型用得好的话,项目在编译之前就几乎把bug找完了。as3的Vector硬搬了泛型这个概念,相比全抄这概念的C#算是弱暴了。
举个例子,List中的itemClass属性能赋值任何类型,如果赋值对象不是显示对象的话,我们只有在项目运行的时候,调整这个List才能知道这个赋值有问题。java的泛型解决了这点,直接来个Class<DisplayObject>这样的变量,如果赋值的不是显示对象,那在项目编译之前就会报错了。
as3没有严格的泛型,所以有严谨性强迫证的同学,就宁愿弃反射而用工厂。因为工厂方法也是可以在编译之前报错的。详细的我就说不了太多,自己也不知道自己是否研究的到可以吹的程度。

 

C语言是没有反射,java是早期的版本没有反射(本人研究不算深,纯属听说)。Adobe在设计as的时候很多高级语言里复杂的东西都被简化了,我们干麻还非要走回高级语言那个套路呢。
as3的Object已经包含有了HashMap的功能,但有些人还是硬生生的又搞一个HashMap类。里面又是一堆看着蛋疼的代码。算了,扯远了,就写这么多。下次有空再扯一下设计模式之接口乱用。以博主懒散的更新的速度,不知道是哪个朝代咯。

转载于:https://www.cnblogs.com/pelephone/p/as3-factory-design.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值