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

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

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

我用一个简单的程序员说法,工厂模式是一个类里面有个工厂,工厂通过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类。里面又是一堆看着蛋疼的代码。算了,扯远了,就写这么多。下次有空再扯一下设计模式之接口乱用。以博主懒散的更新的速度,不知道是哪个朝代咯。

as3设计模式乱用之工厂模式的更多相关文章

  1. java设计模式-----1、简单工厂模式

    简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,简单来说 ...

  2. headfirst设计模式(5)—工厂模式体系分析及抽象工厂模式

    先编一个这么久不写的理由 上周我终于鼓起勇气翻开了headfirst设计模式这本书,看看自己下一个设计模式要写个啥,然后,我终于知道我为啥这么久都没写设计模式了,headfirst的这个抽象工厂模式, ...

  3. Java设计模式(1)工厂模式(Factory模式)

    工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...

  4. 设计模式之单例模式与工厂模式的Python实现(二)

    2. 工厂模式 工厂模式是创建型设计模式的一种.核心的思想是,通过传递给类或函数某种产品的信息来创建产品并返回.当我们想得到产品a对象,只需把产品a的名字传递给工厂函数就能得到产品a对象.而核心思想的 ...

  5. 重学 Java 设计模式:实战抽象工厂模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  6. Java设计模式(5:设计模式的分类及工厂模式详解)

    一.设计模式的分类 总的来说,设计模式可以分为三大类:创建型模式.结构型模式.行为型模式,具体如下图: 二.工厂模式 工厂模式分为简单工厂模式.工厂方法模式和抽象工厂模式.其中简单工厂模式并不属于23 ...

  7. C#设计模式系列:简单工厂模式(Simple Factory)

    1. 简单工厂模式简介 1.1 定义 简单工厂模式定义一个Factory类,可以根据参数的不同返回不同类的实例,被创建的实例通常有共同的父类. 简单工厂模式只需要一个Factory类. 简单工厂模式又 ...

  8. Net设计模式实例之简单工厂模式(Simple Factory Pattern)

    一.简单工厂模式简介(Bref Introduction) 简单工厂模式(Simple Factory Pattern)的优点是,工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类, ...

  9. 10月27日PHP加载类、设计模式(单例模式和工厂模式)、面向对象的六大原则

    加载类可以使用include.require.require_once三种中的任意一种,每个关键字都有两种方法,但是这种方法的缺点是需要加载多少个php文件,就要写多少个加载类的方法.一般也就需要加载 ...

随机推荐

  1. EG:nginx反向代理两台web服务器,实现负载均衡 所有的web服务共享一台nfs的存储

    step1: 三台web服务器环境配置:iptables -F; setenforce 0 关闭防火墙:关闭setlinux step2:三台web服务器 装软件 step3: 主机修改配置文件:vi ...

  2. 斯坦福机器学习视频笔记 Week9 异常检测和高斯混合模型 Anomaly Detection

    异常检测,广泛用于欺诈检测(例如“此信用卡被盗?”). 给定大量的数据点,我们有时可能想要找出哪些与平均值有显着差异. 例如,在制造中,我们可能想要检测缺陷或异常. 我们展示了如何使用高斯分布来建模数 ...

  3. Android LCD(三):LCD接口篇【转】

    本文转载自:http://blog.csdn.net/xubin341719/article/details/9177085 关键词:Android LCD控制器 Framebuffer PWM  平 ...

  4. 【简单dp】poj 1458 最长公共子序列【O(n^2)】【模板】

    最长公共子序列可以用在下面的问题时:给你一个字符串,请问最少还需要添加多少个字符就可以让它编程一个回文串? 解法:ans=strlen(原串)-LCS(原串,反串); Sample Input abc ...

  5. mysql创建定时执行存储过程任务实现订单定时关闭

    CREATE PROCEDURE `tableName`.`procedureName`() LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL SQL SECUR ...

  6. 【整理】C#文件操作大全(SamWang)

    [整理]C#文件操作大全(SamWang) 文件与文件夹操作主要用到以下几个类: 1.File类: 提供用于创建.复制.删除.移动和打开文件的静态方法,并协助创建 FileStream 对象. msd ...

  7. 解决mysql登录报错:ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)

    今天在安装一个压缩包mysql-5.7.19时,碰到了一系列问题,现将这些问题罗列出来: 一.  ERROR 2003 (HY000): Can't connect to MySQL server o ...

  8. vue项目中引入element-ui时,如何更改主题色

    在我们做项目时,我们经常会遇到切换主题色的功能,下面我们就来说一下通过颜色选择器我们就能改变项目的主题颜色 代码如下: 颜色选择器所在组件: top-theme.vue内容如下: <templa ...

  9. 01-THREE.JS 第一个场景

    THREE.JS第一个场景 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  10. 安装Babel(命令行环境,针对Babel6.x版本)

    1.首先安装babel-cli(用于在终端使用babel) npm install -g babel-cli 2.然后安装babel-preset-es2015插件 npm install --sav ...