再看设计模式——访问者模式

visitor模式优势在于双分派 dual dispatch

原始实现:

  1. 消息Visitable接口定义一个结构方法:accept(visitor v) { v.visit(this); }
  2. 访问者Visitor接口定义处理方法:visitor(具体类型) { 具体逻辑 }
  3. 使用者调用:具体类型.accept(v);

这个结构缺点在于新增具体类型,还得修改访问者接口

Acyclic visitor模式实现:消除声明间的循环依赖,每个访问者声明一种专属接口

C++利用泛型实现Acyclic visitor模式,以减少多态类个数:

  1. 声明BaseVisitable基类接口,提供纯虚Accept(BaseVisitor&)方法
  2. 声明BaseVisitor基类接口 , 空类即可, 但要求
    所有visitor类都要实现这个,否则Visitable没法使用统一的Accept方法
  3. 提供DEFINE_VISITABLE宏,加入Accept泛型实现方法,会根据类型Visitor<T>调用对应的visit(T& this)方法
  4. Visitor<T>接口全部继承自BaseVisitor,每个接口提供纯虚visit(T&)方法
  5. 具体访问者要继承Visitor<T>基类,实现具体visit<T>方法

其中一个问题是accept泛型实现中,要根据T将BaseVisitor转换为对应Visitor<T>才可以进行visit方法调用。一种方法是使用dyamic_cast强制转换,还有一种优化是使用hash表:

  1. 声明BaseVisitable基类接口,声明纯虚Accept(VisitorBase* )方法
  2. 声明VisitorBase 基类接口,可以声明纯虚GetFunc方法
  3. BASE_VISITOR_DECLARE 基类使用的宏,提供GetFunc(key)方法实现
  4. VISITOR_DECLARE 声明继承顺序, 提供GetFunc(key)方法实现,该方法先查本身再查基类
  5. VISITOR_IMPLEMENT 调用__RegisterVisitFunc方法向hash表注册所有visit方法(key, visit方法指针)
  6. BASE_DEFINE_VISITABLE 基类使用的宏, 提供 Accept(VisitorBase*)方法,会使用visitor的GetFunc方法获得对于的visit指针,从而进行调用
  7. DEFINE_VISITABLE 声明继承顺序, 提供 Accept(VisitorBase*)方法,同样先调用自身方法,再调用基类

本文是全系列中第6 / 6篇:再看设计模式

打赏作者
提交看法

抢沙发

还没有评论,你可以来抢沙发