老生常谈:抽象工厂模式

    在创建型模式中有一个模式是不得不学的,那就是抽象工厂模式(Abstract Factory),这是创建型模式中最为复杂,功能最强大的模式.它常与工厂方法组合来实现。平时我们在写一个组件的时候一般只针对一种语言,或者说是针对一个区域的人来实现。

    例如:现有有一个新闻组件,在中国我们有这样的需求:在显示新闻列表的同时,附加一个操作:例如给新闻的人气加一。这种需求是非常容易实现的,可是有朝一日你的这个新闻组件应用到了美国呢。你的功能还能满足当地的需求吗?此时美国的需求是:在显示新闻列表的同时,把这条新闻加入到某个RSS中去。可想,不做修改直接用是不行的,那如果直接修改类方法呢?这样实际也是可行的,但是违背了"开-闭"的编程原则,不便以后的维护。 那不修改就只有新加类了,我们可以保留原有功能的同时增加一批类,方法签名都同于之前的,只是实现方式不同而已。为什么要这样做呢?本人的思路是这样的:

    新闻组件无非可以分为两块:

    第一:读取新闻,这是固定不变的,所以可以抽象出来。

    第二:读取新闻同时的附加操作,可以有,也可以没有,可以有一种操作也可以是多种,这里我可以把它们都封闭进一个方法中.这样在外界看起来就是调用了一个方法。所以也可以抽象出来。

    结论:这种情况就是抽象工厂中的系列产品了,生成产品的流程基本都一样,不同的是生产过程。我对新闻组件的改造,具体实现过程如下:先贴出类图:


  

 

      第一:所谓工厂肯定是要有一个最上层的管理工厂了,这里我称为parentFactory,它下面有两个子工厂,我称为:childFactory,分别是负责美国和中国的childFactory_ChinachildFactory_US。parentFactory的责任就是管理好这两个子工厂。生产子工厂实例的方法我用了反射的原理,这样可以在web.config文件中配置就可以决定调用哪一个子工厂来生产产品了。  

Code   

   

      web.config文件中的配置节:

Code


    第二:完成负责美国和中国的childFactory_China和childFactory_US两个子工厂,它们的功能都是一样的,找到合适的工厂(我在这称为:concreteFactory)来完成两个具体部件的加工工作,这两个部件分别是:1读取新闻部件,2:读取新闻后进行的额外操作的部件。这里以中国境内的子工厂为倒来说明:childFactory_China:这个子工厂主要是"找到"具体生产产品的工厂,我在这称为:concreteFactory。

Code

  

   第三:具体工厂部分,我在这称为:concreteFactory,它们负责生成出具体的产品来,对应上面的新闻组件,就是负责生成:1能够读取新闻的部件,2:读取新闻后能够进行相应操作的部件。我在这称为concreteProduct,最终产品。这里就说明一下中国境内的具体工厂的类实现代码,其它的就省略了。

    1:getNews_Class_China:读取新闻部件的具体工厂:

Code

 

    2:otherOperationClass_China:读取新闻后进行附加操作部件的具体工厂.

Code

  

   第四:有了产品当然少不了消费者了,这里我称为customer,customer只与parentFactory和concreteProduc有直接关系,customer可以指定调用哪一个系列的产品。

 

   第五:页面代码:把新闻列表绑定到控件中,同时为了说明问题,把customer在绑定新闻时的附加操作内容以文本的形式显示出来. 

Code

 

   cs:

Code

    第六:运行效果:

     本例有点就模式而模式的意思,其实本人也只是模式的初学者,很难把在实际当中的模式应用拿出来讲,说实在的,本人应用模式特别少。就上面的需求其实有非常多的方法可以实现,只是各有所长而已。在前一段时间,本人学习装饰者模式的时候,就根据同样的需求用装饰者实现过,效果也不错。在网站新闻模块中应用装饰者模式 有兴趣的朋友可以对比看看,不妥处望指教。

     在以下情况下应当考虑使用抽象工厂模式:本人在这就不献丑了,直接引用.NET设计模式(3):抽象工厂模式(Abstract Factory),希望大家不要笑我懒啊  :)

    1:一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。

    2:这个系统有多于一个的产品族,而系统只消费其中某一产品族。

    3:同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。

    4:系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

   总结:在本例中,我们发现抽象工厂虽然能够非常完美的满足需求,但是也有缺点:难以扩展抽象工厂以生产新种类的产品。所有的子工厂都是事先安排好的,如果要生成一个全新的系列产品还是要修改类。

注:

    本文引用:http://terrylee.cnblogs.com/archive/2005/12/13/295965.html

原文地址:https://www.cnblogs.com/ASPNET2008/p/1255726.html