您的位置:首页 > 编程语言 > C语言/C++

设计模式之23 - 访问者模式Visitor

2017-01-13 20:21 423 查看
        访问者模式 属于23种设计模式里面 比较复杂的一种模式,访问者模式就是表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

        说白了 就是被访问者不需要改变,访问者通过继承抽象类操作 来定义对象的访问。

        


抽象访问者(Visitor):声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。

具体访问者(ConcreteVisitor):实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。

抽象节点(Element):声明一个接受操作,接受一个访问者对象作为一个参量。

具体节点(ConcreteElement):实现了抽象元素所规定的接受操作。

结构对象(ObiectStructure):有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。

        提到访问者模式,不得不提到两次分派(double dispatch),这是访问者模式的精髓所在,来看一段代码:

// OSG中节点的访问模式
class NodeVisitor
{
// 构造函数,TraversalMode为节点树的遍历方式
   NodeVisitor(TraversalMode tm)
{
}
// 向下一个需要访问的节点推进
void traverse(Node& node);
// 虚函数,访问各种节点类型,并执行访问器中的自定义操作
   virtual void apply(Node& node);
   virtual void apply(Group& node);
   virtual void apply(Geode& node);
   …………
};

        NodeVisitor 是抽象的Visitor接口,定义来一系列apply接口,子类通过重写apply()函数实现自定义功能。

// osg::Node节点类
class Node
{
// accept
void Node::accept(NodeVisitor& nv)
{
nv.apply(*ths) ; // visit this
}
};


int main(int argc, char** argv)
{
osg::ArgumentParser parser(&argc, argv);
osg::Node* pRoot = osgDB::readNodeFiles(parser);

if(!pRoot)
{
pRoot = osgDB::readNodeFile("cow.osg");
}

ConcreteVisitor visitor;
if(pRoot)
{
pRoot->accept(visitor);
}

system("pause");
return 0;
}


        osg::Node类中的访问接口为 void accept(NodeVisitor& nv),接受一个访问者,访问者反过来在函数里面实现对当前对象的访问,这就是两次派遣(double dispatch)。

        double disptch 可以概括为: 从节点接受一个访问器开始,到节点反过来执行访问器的apply()函数,并将自己传入访问器。

        访问者模式 是一种非常有价值的模式,在开源引擎OSG中的大量使用也说明了这一点(对于树形结构的访问 Visitor模式有一定优势),但需要注意的一点是,访问者模式适合在模型对象相对稳定的情况下,主要在于对于 不同访问者 的扩展。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息