1.Visitor模式:将更新(变更)封装到一个类中(访问操作),并由待更改类提供一个接收接口,则可在不破坏类的前提下,为类提供增加新的新操作。

2.Visitor模式结构图

Visitor模式的关键是双分派(Double-Dispatch)的技术:Accept()操作是一个双分派的操作,具体调用哪个Accept()操作,有两个决定因素(1)Element类型(2)Visitor类型。

3.实现

 #ifndef _VISITOR_H_
#define _VISITOR_H_ class Element; class Visitor
{
public:
virtual ~Visitor();
virtual void VisitConcreteElementA(Element* elm) = ;
virtual void VisitConcreteElementB(Element* elm) = ;
protected:
Visitor();
private:
}; class ConcreteVisitorA:public Visitor
{
public:
ConcreteVisitorA();
virtual ~ConcreteVisitorA();
virtual void VisitConcreteElementA(Element* elm);
virtual void VisitConcreteElementB(Element* elm);
protected:
private:
}; class ConcreteVisitorB:public Visitor
{
public:
ConcreteVisitorB();
virtual ~ConcreteVisitorB();
virtual void VisitConcreteElementA(Element* elm);
virtual void VisitConcreteElementB(Element* elm);
protected:
private:
}; #endif

Visitor.h

 #include "Visitor.h"
#include "Element.h"
#include <iostream>
using namespace std; Visitor::Visitor()
{ }
Visitor::~Visitor()
{ }
ConcreteVisitorA::ConcreteVisitorA()
{ }
ConcreteVisitorA::~ConcreteVisitorA()
{ }
void ConcreteVisitorA::VisitConcreteElementA(Element* elm)
{
cout<<"i will visit ConcreteElementA..."<<endl;
}
void ConcreteVisitorA::VisitConcreteElementB(Element* elm)
{
cout<<"i will visit ConcreteElementB..."<<endl;
}
ConcreteVisitorB::ConcreteVisitorB()
{ }
ConcreteVisitorB::~ConcreteVisitorB()
{ }
void ConcreteVisitorB::VisitConcreteElementA(Element* elm)
{
cout<<"i will visit ConcreteElementA..."<<endl;
}
void ConcreteVisitorB::VisitConcreteElementB(Element* elm)
{
cout<<"i will visit ConcreteElementB..."<<endl;
}

Visitor.cpp

 #ifndef _ELEMENT_H_
#define _ELEMENT_H_ class Visitor; class Element
{
public:
virtual ~Element();
virtual void Accept(Visitor* vis) = ;
protected:
Element();
private:
}; class ConcreteElementA:public Element
{
public:
ConcreteElementA();
~ConcreteElementA();
void Accept(Visitor* vis);
protected:
private:
}; class ConcreteElementB:public Element
{
public:
ConcreteElementB();
~ConcreteElementB();
void Accept(Visitor* vis);
protected:
private:
}; #endif

Element.h

 #include "Element.h"
#include "Visitor.h"
#include <iostream> using namespace std; Element::Element()
{ }
Element::~Element()
{ }
void Element::Accept(Visitor* vis)
{ }
ConcreteElementA::ConcreteElementA()
{ }
ConcreteElementA::~ConcreteElementA()
{ }
void ConcreteElementA::Accept(Visitor* vis)
{
vis->VisitConcreteElementA(this);
cout<<"visiting ConcreteElementA..."<<endl;
}
ConcreteElementB::ConcreteElementB()
{ }
ConcreteElementB::~ConcreteElementB()
{ }
void ConcreteElementB::Accept(Visitor* vis)
{
cout<<"visiting ConcreteElementB..."<<endl;
vis->VisitConcreteElementB(this);
}

Element.cpp

 #include "Element.h"
#include "Visitor.h"
#include <iostream> using namespace std; int main(int argc,char* argv[])
{
Visitor* vis = new ConcreteVisitorA();
Element* elm = new ConcreteElementA();
elm->Accept(vis); return ;
}

main.cpp

4.Visitor模式的缺点

(1)破坏了封装性

(2)ConcreteElement的扩展很困难:每增加一个Element的子类,就要修改Visitor的接口,使得可以提供给这个新增加的子类的访问机制。

最新文章

  1. 1Z0-053 争议题目解析25
  2. WPF三种基本触发器与【与或】逻辑触发器
  3. Qt 5.7 版本+2013VS环境配置
  4. 2013 ACM-ICPC长沙赛区全国邀请赛—Special equations
  5. Cocos2d-x优化中关于背景图片优化
  6. [Swift]LeetCode563. 二叉树的坡度 | Binary Tree Tilt
  7. form表单获取多选的值
  8. 五一培训 DAY1
  9. vue 百度地图实现标记多个maker,并点击任意一个maker弹出对应的提示框信息, (附: 通过多个地址,标记多个marker 的 方法思路)
  10. php 公历阴历互相转换
  11. chmod a+r file:给所有用户添加读的权限
  12. Redis哨兵(sentinel)模式搭建
  13. 34.More-healthyful Menu Options for Kids 给孩子提供的更健康菜式选择
  14. 第二十一章 springboot + 定时任务
  15. linux用户 群组权限
  16. Codeforces Round #241 (Div. 2) B. Art Union 基础dp
  17. ABAP读取长文本的方法
  18. IOS开发学习笔记005-数组
  19. DeepFaceLab小白入门(3):软件使用!
  20. android摄像头获取图像——第三弹

热门文章

  1. TStringList的Find,IndexOf和Sort
  2. hdu 1575(矩阵快速幂)
  3. AC日记——Number Sequence hdu 1711
  4. 2017CCPC 哈尔滨 B
  5. Codeforces Gym101502 K.Malek and Summer Semester
  6. 某考试 T2 bomb
  7. Ubuntu 16.04安装Wine版的迅雷+QQ(完美方案,终极解决方法)
  8. Xcode: This device is no longer connected error
  9. stateMachine 相关知识
  10. 随想录(fatfs的学习)