现在的位置: 首页 > 综合 > 正文

从抽象到模式——面向对象之旅(三)、设计模式的力量

2013年09月11日 ⁄ 综合 ⁄ 共 1708字 ⁄ 字号 评论关闭

  上一节,我们引入了一个不大不小的变更,然而不经思考的编码却给我们带来了不少麻烦。万不得以,只能重构。

  现在臭味消除了,我们Filter类中的InitRules回来了,同时我们也派生了两个规则读取的子类,供过滤器子类使用。

  

  等等,有个问题。你的题目是从抽象到模式,到现在我们都只看到抽象了,那么模式又在哪儿呢?

  模式来了,首先我们要引入两个设计模式,分别是Template Method和Strategy。

  

  请看我们的RuleReader,它有一个初始化函数InitRules(),通过调用GetDefaultRules()和GetConfigRules()来完成规则的初始化工作,这里有一点,就是InitRules()不是virtual function,它的逻辑是固定的,子类不需要重写它,而是要重写它所调用的另外两个函数。当客户使用InitRules()的时候,它就会动态地调用子类的GetDefaultRules()和GetConfigRules()。

  这就是Template Method,如果某一算法的基本逻辑是不变的,只是其中的几个策略点实现的方式不同,那么我们可以在父类中用一个非虚函数实现算法的基本逻辑,并将可变的策略设计为虚函数供子类继承。

  可能用RuleReader做Template Method的实例比较牵强,下面我们引入另一个例子:泛式的快速排序算法。快排的逻辑是固定不变的,但是按从小到大还是从大到小的顺序排列,元素之间大小比较是如何判断的等等,这些策略可能不同,因此可以把算法逻辑提取出来成为父类的非虚接口,同时把排列结果的顺利和大小比较策略抽象化成虚拟的接口,那么我们就可以用子类来具体化一个特定的快速排序算法。

 

  但是Template Method有一个缺点,那就是算法逻辑必须是固定的,当我们需要灵活的算法逻辑时该怎么办呢?没关系,别着急,该是Strategy出场的时候了。

  Strategy使用父类定义一个抽象的接口供客户调用,子类可以实现这一接口从而完成不同的算法逻辑。客户把父类的引用(或者指针)作为自己的成员变量,并在客户代码中通过这一引用动态地调用父类提供的抽像接口。当我们把不同的子类对象赋值给父类引用的时候,客户端即可实现不同的算法策略。

  那么Strategy在我们的项目中有用到吗?请看我们的PlugIn类中的m_Filters,只是它在那里担当的角色是一个策略组而已。

 

  (未完,待续......)

 

抱歉!评论已关闭.