`
凤舞凰扬
  • 浏览: 65446 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

架构、框架、模式之轻松掌握设计模式(工厂模式)

阅读更多
 说起工厂模式,哈,几乎所有的开发人员都知道,但是,估计百分之八十以上的人用得比较滥(嘿嘿,注意哦,我用的是滥,而不是烂)。
 好吧,先简单介绍一下工厂模式。在GOF中,工厂模式有两种,工厂与抽象工厂,而实际上,有三种,也就是简单工厂。
 简单工厂一般由三种对象构成(工厂对象,抽象产品对象,具体产品对象),工厂模式一般由四种对象构成(工厂接口,产品抽象,具体工厂,具体产品),而抽象工厂则至少由7个以上对象了。(抽象工厂,两种以上不同的产品抽象对象,两种以上不同的工厂实现对象,两种以上不同的具体产品对象)。哈哈,复杂吧!来,我们用个很简单的实际生活中的例子来说明一下。简单工厂的例子是最常见的了,我们把抽象产品对象理解为一种产品,拿电脑来说事吧,945的主板就相当于抽象产品,ASUS就相当于简单工厂,为了针对不同的人群和需求,那么就可以偷工减料,也可以狠砸money,自然出来的产品就不同咯。对于使用者某种需要来说,关心的就是是否是945的板子,是否支持Intel的CPU。好,再让我们来看看工厂,DELL是发包商,它发现微星的板子比华硕的便宜一些,又同意是945的板子,那么它就会根据需要,调整不同的厂商来制作不同的板子,当然都是统一类型。这时候,朋友们可以发现了吧,简单工厂和工厂使用者上的不同,稍后再继续讨论这点。抽象工厂,神舟电脑公司就想贴牌,所以它要找些产品线丰富的厂商来生产,这样可以提高兼容性。好了,它需要一个抽象的工厂,这个工厂生产主板,显卡还有其他一些设备。但是呢,它经常需要根据实际的一些需要和条件来改变这个实际生产的厂商了。好了,华硕、微星接到了订单,他们担任实际的工厂了,产品嘛,就是显卡和主板,当然,两个厂商会根据需要生产出自己独特的产品,尽管型号一样。我们把角色对上位,大家可以一目了然了吧。
这里我们就带来了设计模式的一个重要的概念,既然面向对象是生活的抽象,事物都可以以对象描述,那么作为一种解决方案的模式,它就肯定表明了生活中常见的例子。那么好,为什么要用模式,哪些地方可以用这个模式。我们看看生活中的情况,也就一清二楚了。
我们可以看出,三种工厂模式使用的区别在于使用者上,使用者有不同的需求,那么就会需要调整相应的结构。在我们实际工作中,很多时候,实例对象的构造比较简单,所以很多时候简单工厂的应用比较广泛。但是,被滥用的也是它了。为什么呢,首先,我们需要了解为什么要使用它?其实这里有个隐含的概念,也就是单元。不知道朋友们是否发现,在每一个模式的图里只画出了内部的结构,而并没有画出调用者(最多也只是一个辅助的角色出现,只是为了说明调用的关系)。那么工厂模式运用的地方又是在哪里呢?根据前面的例子描述,我们可以看出,它是用在单元外部与单元内部的交互上了。这也就是所有创建模式的分类原因。我们这提这样一个问题,在单元内部是否可以使用工厂呢?单元又是一个多大的概念呢?我们说吧,在单元内部使用工厂(包括简单工厂)往往是种滥用,因为面向对象设计原则告诉我们,对象是可扩展,而不应被修改(也就是开闭原则)的。如果我们追求的是单元的复用,而不仅仅是某个类的复用,过多的使用工厂,只会是堆砌无用的代码而已。至于单元的大小又如何确定呢?想想你要复用的最小结构吧,那就是单元。好了,又会有朋友说,那如果不用工厂,我如果想改变一些实例,怎么办?嘿,我就告诉大家一个经典的设计,其实也就是在jdk实现中广泛运用的设计方式,Wrapper实现。 所有java的开发人员都非常清楚Map, Set , List ,这样的接口,在我们使用的时候,不会有哪位朋友去用工厂生产他们的实例吧?用的话,赶紧改哦。我们知道,常用的实现HashMap / HashSet / ArrayList都是可以修改的,线程不安全的。我们往往遇到一种尴尬,当我们返回List, Map , Set他们实例的时候很少考虑到他们也许会出现并发问题,他们也许会被别人修改内部的内容。怎么办?让我们看看Collections这个类吧, 在JDK1.4及以前的版本里,它提供了unmodified, synchronized的封装。传接口普通实例进去,返回接口的封装实例。对了,这就是非常经典的接口+(抽象类)+标准参考实现+封装实现。它就可以代替工厂在单元内部的使用者使用了。
那么好,在针对单元外部使用者来说,究竟是用工厂还是抽象工厂呢?他们的优缺点又在哪里呢?我们可以看看,对于工厂模式,一般必须由外部使用者指定它的工厂实例(变种的除外,到时候会讨论所谓变种的问题),当然对于内部实体来说,它可以供外部者更改或参考。对于在不考虑单元外部程序复用的情况下,它是不错的。而抽象工厂了,其实它的关注角度已经由产品移到了工厂上,同时它考虑了产品实例和工厂实例交叉的问题。换言之,其实就是将关系由一对多,变成了多对多。它的优点是提供了多种组合可能性。它存在的问题呢?想要增加一种产品的时候会发现它无法扩展了(这是很多人总结的一些问题,不过这个问题真的存在么?存在的话,那是不是就已经改变了抽象工厂模式应用的基础呢?离开了应用环境基础的话,又怎么回是抽象工厂模式本身的问题呢?) 一般来说,对于服务型对象的工厂,使用抽象工厂模式比较合适(有更好的扩展性);而一般对于实体型对象的工厂呢,使用工厂模式就相对简单,也更加让人容易明了。
总结一下,世界上没有那种东西是放之四海皆准的真理,模式也一样。模式存在的本身是在某种环境下应用实践的总结,离开了对应的环境,所招来的骂名,我想它们也是会委屈滴…… 所以,朋友们,不要随便骂哪个模式如何烂,如何不好。不好的只是我们用滥了。
 
  • 大小: 25.5 KB
  • 大小: 15.1 KB
  • 大小: 9.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics