7.5.2 使用访问者模式添加函数

728 篇文章 1 订阅
48 篇文章 0 订阅

7.5.2 使用访问者模式添加函数

 

    在已有的数据结构上添加新的操作,是函数语言中实现处理数据的任何代码的主要方式。在面向对象的语言,很难做到,也很少需要。在这一节,为此目的,我们将讨访问者模式,将草绘如何,使用它在我们的文档表示中添加操作。图 7.8 显示的是我们在这一节要用到的基类。

 

7-8

图 7.8 表示文档的类层次,和泛型访问者类,状态作为泛型类型参数 (T);由于 Accept 方式,所有部件都支持这个访问者。

 

    从抽象类 DocumentPart 继承的类的层次,在面向对象编程中,是表示可选值的一种常见方法,它对应于 F# 中差别联合类型 。

    访问者模式的主类是一个泛型类 DocumentVisitor 。我们使用一个模式变量,来处理状态,因此,类参数型 T 表示我们需要维护的状态的种类,比如,参数值,或者,由访问者模式执行一些计算的结果。该模式还需要添加虚方法 Accept,在每个派生类在实现。这个方法取访问者模式作为参数值,调用适当的 Visit 方法,取决于它是哪个部件。可以在本书的网站中找到完整的源代码,我们看一下在 ImagePart 中的 Accept方法的代码:

 

public override T Accept(DocumentPartVisitor visitor, T state) {
  return visitor.VisitImagePart(this, state);
}

 

    这个方法只委托处理给访问者对象。因为,它在每个派生的类中实现,可以调用 VisitImagePart,其参数值是实体类(在本例中 ImagePart)。这意味着,当我们实现一个实体访问者时,将有一个容易和类型安全的方式,去访问表示文档不同类型的属性。

    清单 7.18 显示了如何添加一个操作,使用访问者模式,在面向对象表示的文档中,统计单词数。

 

Listing 7.18 Counting words in the document using the visitor pattern (C#)

 

class CountWords : DocumentPartVisitor {
  public override int VisitTitledPart(TitledPart p, int state) {
    return p.Text.Text.Split(' ').Length +
      p.Body.Accept(this, state);
  }
  public override int VisitSplitPart(SplitPart p, int state) {
    return p.Parts.Aggregate(state, (n, p) =>
      p.Accept(this, n));
  }
  public override int VisitTextPart(TextPart p, int state) {
    return p.Text.Text.Split(' ').Length + state;
  }
  public override int VisitImagePart(ImagePart p, int state) {
    return state;
  }
}

 

    这段代码对应于 F# 中写的递归函数,使用模式匹配来检查,我们当前正在处理的是哪一个部件。在面向对象的方法中,这个选择是在访问者模式中的 Accept 方法完成的。CountWords 类从访问者继承,使用一个 int 值作为状态。处理文档部件不同类型的方法,把单词数加到当前状态,有两种方法,必须以递归方式在特定的子部件上调用这个访问者。该调用是通过在子部件上调用 Accept 方法完成的,类似于我们需要在整个文档上运行的处理代码:

 

int count = doc.Accept(new CountWords(), 0);

 

    在这里,我们调用 Accept 方法,并为其提供访问者一个新的实例作为参数值。如果我们想要添加另外的操作,我们可以实现一个新的类,与 CountWords 类似,把它作为参数值给 Accept 方法执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值