Visitor模式,Decorator模式,Extension Object模式

  • Modem结构
  • Visitor模式
    • 对于被访问(Modem)层次结构中的每一个派生类,访问者(Visitor)层次中都有一个对应的方法.
    • 从派生类到方法的90度旋转.
    • 新增类似的Windows配置函数时,Visitor模式使用Visitor派生类来代替了被访问者结构中的方法.
    • 双重分发:accept()+visit()两个动态分发.
    • 形成了一个功能矩阵:不同类型的Modem的轴线+不同OS的轴线.每一个单一都被一个功能(描绘了特定的Modem在特定的OS中使用的)填充.
  • Acyclic Visitor模式
    • Visitor模式的问题
      • Modem依赖于ModemVisitor.
      • 依赖环:Modem中每一个派生类在Visitor接口中都有一个对应的函数.这样将派生类绑定在一起了.
      • 当Modem层次结构很不稳定,经常需要创建新派生类时,需要改动Visitor的整体继承结构.
    • 将ModemVisitor退化为一个标记接口.
    • 对于被访问层次结构中的每一个派生类,都有一个访问者接口.
    • 从派生类到接口的180度旋转.
    • 解除了依赖环,易于增加被访问者派生类.
    • 创建了一个稀疏矩阵,访问者只需要针对需要使用的被访问者派生类进行实现处理.
  • Visitor模式的用途.
    • Application中存在有需要以多种不同方式进行解释的数据结构时使用.
    • 遍历大量的数据结构并产生报表.使得数据结构对象中不含有任何产生报表的代码.
    • 例如,编译器的中间数据结构,APP中的配置数据结构.
    • 使用访问者时,所使用的数据结构都独立于它的用途.
    • 访问者的更改和新增,不会影响现有数据结构的重新编译和部署.
  • Decorator模式
    • Visitor模式之外,另一种可以在不改变现有类层次结构情况下向其中增加新方法.
    • 针对最初的Modem设计,有些用户希望在Dial时听到拨号声,而另一些希望安静.
    • 使用Template Method的方案:将Modem从接口变成类,并持有wantsSound变量,在Dial方法中,判断是否出声.
    • 但是问题在于,Modem本身是不应该受到非其内在功能(拨号,链接)之外特性的影响而变动.
    • 如果需要多个装饰者,那么添加一个ModemDecorator类来实现Modem接口.其它装饰者都继承自它.
  • Extension Object模式
    • 不更改类层次结构时,向其中新增功能.
    • 层次结构中每一个对象都持有一个特定扩展对象的List.
    • 通过扩展对象提供了操作原始层次结构对象的方法.
    • 对于一个材料单系统,我们希望将数据输出到XML和CSV两种介质中去.
    • 使用Visitor模式,会把Assembly/PiecePart及其它Part类型的输出XML的代码混合在一个Visitor对象中.
    • 当我们想分离每种Part类型和每种输出介质类型的逻辑时,使用ExtensionObejct模式.
    • BadPartExtension对象用于在getExtension()方法未找到合适的Extension Obejct时的返回值.
    • 扩展对象是在每一个Part对象(Assembly/PiecePart)的构造函数中装入该对象中的
      • Assembly()
        • {addExtension("CSV",new CSVAssemblyExtension(this));
        •   addExtension("XML",new XMLAssemblyExtension(this));}
      • 也就是part对象扔依赖于XML和CSV类.
      • 可以使用Factory对象去创建Part对象并装入扩展对象.

[Agile Software Development(Principles,Patterns,and Pracitices)]

posted @ 2013-12-14 14:38  robynhan  阅读(481)  评论(0编辑  收藏  举报