评设计模式

纪录一下关于设计模式的思考,这些想法,可能会日新月异。

1.Visitor 模式

   此模式核心是把对元素的操作封装起来了。其实实现的就是C#委托功能的一部分应用.因为当年的Java没有委托可用,所以产生了这种模式.

 委托就相当于Visitor的基类或接口。

 如果对元素的操作可以明确归纳为几类的话,可以按此模式的标准写法,来定义Visitor的基类或接口,然后定义具体的Visitor类;否则的话,用委托即可,不用维护一个Visitor类系列,增加程序的复杂性。

   举个例子,写一个递归遍历树形控件的方法,如果对树结点的操作方式就那么几种,可以把方法的参数定义为Visitor的基类或接口,对每一个树结点,使用参数传入的Visitor具体子类进行处理;否则的话,可以把方法的参数定义为委托,对每一个树结点,使用参数传入的委托进行处理,其实这时方法就变成了和具体应用程序无关的通用方法了。

   谈到此模式,一般会涉及到双重分派的概念。它的意思是这样的:在处理过程中调用了两次参数是接口或基类型的方法,这两次调用传的是接口或基类型的具体实现类或子类,这样的话CLR会在运行时两次具体确认参数的具体类型,从而正确调用方法的重载(也就是因为可能会存在参数是基类或具体子类的两种方法重载)。CLR的每一次处理,可称为一次分派。像上面的例子,只有一次分派。看下面的情况:

   有集合元素基类E,子类SubE1,SubE2

   有集合基类C,子类SubC1,SubC2. 基类C有元素类型是E的集合类型属性Items,SubC1和SubC2重写了Items属性,使其元素类型分别为SubE1,SubE2。

   定义Visitor基类D及子类,其名为F1的处理方法的参数类型都是E

   C有一个遍历所有Items的方法F2,参数类型是D. 在遍历调用过程中,对每一个元素X,使用F1方法并把元素X传给此方法。

   这样在实际调用时,由于实例的Visitor类的不同,则会导致CLR对F2在运行时具体的参数类型进行确定过程,这就是第一次分派,而在F2内部过程中,在调用F1时由于元素实例的类型不同,会导致CLR对F1在运行时具体的参数类型进行确定过程,这就是第二次分派。

   上述例子就是双重分派,随着程序复杂程度的增加,就可能会产生多次参数类型确定过程,就是所谓的多重分派啦。    

2.Observer 模式

   此模式核心是类维护一个与其相关的类的列表,当类的状态发生变化时,遍历列表,对其元素进行操作。

 .Net的Trace功能的Listener的应用就是Oberver 模式的典型应用

3.Abstract Factory 模式 和 Factory Method  模式

   两个模式的核心是强调:

  1)使用接口构建对象体系(对象系列)

  2) 使用Factory类封装类实例化操作,以取代直接使用类的构造函数来实例化类

  3) 对Factory类的体系也使用接口进行抽象

   对第一点是毋庸置疑的。

   对第二点是需要探讨的,好是好,不过不要为了完美而完美,实用最好。很多时候,new够用了。变化没那么多。完美是完美了,不过,程序复杂度增加了。说到这儿,很多人都知道,设计模式的讲解过程中,类们是糟老罪了,被一分为二,然后二分为四,再然后四分为八,用老话讲是太级生两仪,两仪生成四象,四象生八卦,呵呵。按标准模式写法建了一组类,嗯,是挺精致的,不过是不是有点复杂了。当你因为某种原因大脑已经变得很缺氧时(比如已经干了一天活),想改点儿功能,你打开了一个类文件,噢,不是它,然后又打开了一个类文件噢,不在这儿,然后又打开一个类文件,噢,该死的,到底在哪儿...噢,想起来,在那个类文件里。我讨厌无谓的复杂,为了屁大的事儿,就搞得的这么复杂,当然因为程序的物理分层、逻辑分层搞得复杂是没有问题的。我喜欢简单,我希望我改一个地方就改好了,我讨厌改一二三四。记得某天看.net 3.5工作流的官方样例程序,好像建一个状态,就要建四个左右的类,还不放在一起,我当时就晕了,大哥,用不用这么优美?!马上评级为非优等,果然,现在.net 3.5工作流还是非主流,呵呵,当然这跟我的评级是没关系的。

   对第三点,如果要支持插件功能的话,应当如此。

 

   这两个模式没有本质区别,他们的区别是Abstract Factory模式中的工厂会创建非同一基类的多个产品,这样有多个工厂的话,就会产生多个产品的多个系列;而Factory Method模式中各个工厂只创建同一个基类的产品,并且每个工厂只生产一种产品,这样通过多个工厂完成了一个产品的一个系列的实现。

   可以说Factory Method模式是Abstract Factory模式的极端情况。

   形像的说,比如有以下矩阵

         英语版产品  法语版产品  德语版产品

  I电玩软件   英版暗黑        法版暗黑         德版暗黑

  I电玩玩具   英版公仔        法版公仔         德版公仔

  I电玩包具   英版背包        法版背包         德版背包

      相当于Abstract Factory模式的每个工厂要创建矩阵的每一列的产品,而Factory Method模式的所有工厂共同完成矩阵的某一行产品的创建,每个工厂只创建一种具体产品(即如果用Factory Method模式来实现矩阵,则要用三次)

  

4.Singleton 模式

 此模式核心是保证类的实例即使在多线程程序中也是唯一的。

 这其实挺难的,有同事说,两重锁(lock指令)都锁不住。

   费这劲干吗,其实这种类的实例的创建都是一个核心程序员来做的,只要创建一次即可,然后告诉其他人如何用此实例、并在合适的文档位置注释清楚即可。

   另外的话,我一直困惑,在C#中用静态类来实现单例的功能不行吗?我理解大概是因为静态类和类的实例的内存位置不同。有人说有的时候用静态类解决不了问题,就得用单例,但没给例子,我想了半天,也没想出来这是什么样的情况,难道是多线程的情况吗?有的时候,我怀疑此模式的产生跟Java当年静态类的某种不便之处有关,现在对于C#,可能不太适用。

   补充:  

  按园友Zhenway的对上述问题的解释“静态类不能作为某接口的实例,而单例可以;另外单例保留了以后变成多例的可能性”来看,使用单例模式是从使用范围和可扩展性角度来说的。

  

 

 

posted on 2010-05-11 21:36  Apollo Sun  阅读(1621)  评论(2编辑  收藏  举报

导航