ASP.NET2.0

网站开发

用抽象工厂模式武装新闻组件

    在创建型模式中有一个模式是不得不学的,那就是抽象工厂模式(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,最终产品.这里就说明一下中国境内的具体工厂的类实现代码,其它的就省略了.

 

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

 

Code

 

   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

Tag标签: C#,.NET

posted on 2008-07-29 16:46 姜敏 阅读(1323) 评论(10)  编辑 收藏 所属分类: ASP.NET2.0设计模式

Feedback

#1楼  2008-07-29 16:50 Gray Zhang      

好麻烦……在取新闻的那个类上再套一层装饰处理一下不就好了……   回复  引用  查看    

#2楼 [楼主] 2008-07-29 16:52 姜敏      

@Gray Zhang
你说的没错,在之前的文章中,我已经应用装饰者实现过,不过用抽象工厂也不错,这样可以通过配置为决定调用哪一个方法。反射的效果还真不错。:)   回复  引用  查看    

#3楼  2008-07-29 16:54 Gray Zhang      

@姜敏
你的实现是很不错,但我有一个问题,other_method这东西怎么知道他要操作的新闻是哪一条?你的方法没有传值,而且get_newsClass也不知道other_method的存在(也确实不应该知道),那么怎么把新闻的相关信息(比如主键值)交给other_method呢   回复  引用  查看    

#4楼 [楼主] 2008-07-29 16:59 姜敏      

@Gray Zhang
你看的非常仔细啊,是的,我并没有和具体的新闻关联起来,只是在绑定新闻后,两次调用了这个方法,这主要是主了说明问题,并没有做的那么具体,误导你了,哈哈。   回复  引用  查看    

#5楼 [楼主] 2008-07-29 17:01 姜敏      

不过要是写的话,也不困难,绑定完控件后,取得新闻ID,然后修改下程序,给它传个新闻ID就行了。   回复  引用  查看    

#6楼  2008-07-29 17:02 Gray Zhang      

@姜敏
我担心的是,根本没有办法向other_method传送需要修改的新闻的相关信息,这里把不应该解开的耦合给解开了,导致模块之间无法建立联系……如果你可以修改一下示例让other_method获取到新闻的相关信息就好了
上回装饰模式那个已经讨论了不少了,现在还在用新闻模块搞啊~   回复  引用  查看    

#7楼 [楼主] 2008-07-29 17:06 姜敏      

@Gray Zhang
你的意见的记住了,到时候改下,其实我也只是个模式的入门者,所在没有太好的例子来说明这个问题,见谅了,哈哈,经验不丰富的原因。   回复  引用  查看    

#8楼 [楼主] 2008-07-29 23:15 姜敏      

@金色海洋(jyk)
本文可能在这个例子上不太具备代表性,可能看起来会小题大作,但是仔细看的话,也是有道理的,试想如果这个新闻组件适用的语言多达四个或者更多,而且附加处理的方法又各不相同,此时就会体现它的优点了.   回复  引用  查看    

#9楼 [楼主] 2008-07-30 08:28 姜敏      

@金色海洋(jyk)
可能本人写的太差,误导你了,见谅,我是以新闻模块为例来说明抽象工厂,可能例子不太符合吧,不过个人认为还是符合的.   回复  引用  查看    

#10楼  2008-07-30 14:35 雅阁布      

up!!!   回复  引用  查看