不用代码和类图说设计模式(1)

2007年3月17日 | Author: zhangdi | 标签: , ,

最近在重新学习C++,也在看公司产品的代码,深切体会到一个大型的项目如果没有很好的代码设计,会为维护带来过大的成本。我想说的代码设计,并不是产品层次的设计,而是developer在写程序的时候,如何设计自己实现功能所使用的编码方式和模式。这就是为什么我突然决定复习设计模式了。我看设计模式还是在大学,虽然多少还有些印象,但真正能拿起来用的就那么几种经常用到的。但设计模式是针对不同问题的不同best practice,所以如果有一种不知道,就可能在coding的时候走弯路,甚至走错路。

我希望能把我复习的过程写成一系列的文章,而且不想用代码和类图来说明,因为这些东西在所有介绍设计模式的书里面都很多,我只想把我复习的心得和问题写出来。难免有错误,希望任何人指出。:)

一、Factory, Abstract Factory, Factory Method模式

这三个模式都跟Factory这个词有关系,所以都是用来创建对象的模式。我最初看到这三个模式的时候,真是有点晕,都是factory,有什么区别呢?在什么时候需要用哪个呢?

先来讲三个故事:

1、一个匪徒,我们叫他Mr. Pattern,为了要实施对一个银行进行抢劫,需要买一支武器。但他不知道买什么,所以他来到了一家叫”WeaponFactory”的武器店。他说了他想要武器后,营业员说,我们这里有A系列手枪、B系列手枪、A系列自动步枪、B系列自动步枪甚至还有Z系列火箭筒,你想要什么就去相应的柜台交钱,然后就可以拿到货了。

2、还是这个Mr. Pattern,他决定不在”WeaponFactory”买了,因为那里武器全都摆在一起,太多了,导致店铺太大,根本就没办法逛,而且据说后来因为无法再扩大营业面积最终倒闭了。这次他来到了一个叫“AbstractWeaponFactory”的店。他这回多了个心眼,透着窗户看了看,恩,这回里面不是很乱,好像店里面就摆了一个系列的产品。他不知道这个系列是不是他需要的,抱着试试看的想法,他踏入了店门。突然,一阵眩晕,等再清醒过来,看到面前摆的都是C系列的产品:手枪、步枪等等。这时,一位美丽的导购小姐走过来,对Mr. Pattern说:“感谢您的光临,我们已经根据您的需求和所处的环境,将您自动传送到我们的C系列子店中,在这里您可以买到所有您需要的产品”。Mr. Pattern幸福的晕过去。

3、Mr. Pattern经历过”AbstractWeaponFactory”的美好体验并且成功使用C系列产品打劫了一家银行后,在业内非常出名。他现在有钱了,想要点高级货。这次他来到一个名字叫“FactoryMethod Weapon”的店铺。这里的东西似乎没有什么特别的,当Mr. Pattern正要离开的时候,发现每个武器上都有一个小按钮,上面写着“弹药”。难道武器可以自己提供弹药?他按了一下手枪上的,果然有手枪子弹从一个枪身侧面一个隐秘的小口一颗一颗的挤出,正好装满一个弹夹的数量。他又按了一下步枪上的,这次直接从枪托中弹出一个完整的弹夹。Mr. Pattern很兴奋,他不怀好意的又按了一下火箭筒的,似乎没有什么反应,哈哈,也有不灵的,突然这时,门外响起汽车急停的声音,冲进来一个人,这个人全副武装,怀里抱着一颗火箭弹。

这三个故事并不是想说哪个店铺经营最成功,而是想分别举例说明Factory, Abstract Factory和Factory Method三个设计模式的特点。

Factory Pattern: 简单的构造对象。优点是简单,封装对象的构造过程。通过配置和参数,可以某种程度替代Abstract Factory的工作。缺点是只能应对简单的情形,复杂的情况下,很容易导致代码冗长,有太多的条件判断等等。

Abstract Factory Pattern: 根据情景,构建一组关联的对象。优点是: 结构清晰,每个系列的对象在不同的concrete factory中,每次用户只能拿到一个concrete factory, 所以不会有混用的情形。缺点,每多一个系列都要有一个相对应的concrete factory。

Factory Method Pattern: 将创建的操作交给子类来做。比如说,我们要弹药,是写一个Factory来提供各个型号的弹药呢;还是写一个Abstract Factory来根据我们手中的武器得到相应系列的concrete factory,再通过相对应的方法来得到弹药呢;还是我们跟武器说,我们要弹药,然后这个武器自己给你了呢。这就是Factory Method。优点是,提供一个逻辑很清晰的创建对象的接口。缺点是,每个子类都要实现Factory Method,所以当子类过多并且需要创建的对象的种类也过多的时候,就应该考虑使用Abstract Factory来解决问题了。

总结一下,Factory就是简单的创建对象,确实一定要简单,越复杂的情形,就越应该用别的模式;Abstract Factory是针对需要构造的对象明确的分为几个系列,GoF中使用family,我觉得很确切。需要另外的机制,使用户透明的得到concrete factory,比如,配置文件,系统参数等等;Factory Method针对要构造的对象明确的与子类相关。比如,武器的“获得弹药”这步构造,明确地与子类相关,每种武器都不一样,所以我们就把构造的任务交给各个子类,当然,如果不光要弹药,我还要各种零件,那就还不如提供一个资源箱(Abstract Factory)。不过,话说回来,具体情况具体分析。就像具体编码的时候,Factory Method可能是通过Abstract Factory实现的,而Abstract Factory可能通过Factory组成。总之,面对一个问题,找到最适合的模式,那就是高手了。

目前还没有任何评论.