设计模式(17) 访问者模式(VISITOR) C++实现

意图:


表示一个作用于某对象结构的各元素的操作。它使你可以再不改变各元素的类的前提下定义作用于这些元素的新操作。

动机:


之前在学校的最后一个小项目就是做一个编译器,当时使用的就是访问者模式。

在静态分析阶段,将源程序表示为一个抽象语法树,编译器需要在抽象语法树的基础上实施某些操作以进行静态语义分析。可能需要定义许多操作以进行类型检查、代码优化、流程分析、检查变量是否在使用前被赋值,等等。

这个需求的特点是:要求对不同的节点进行不同的处理。

常规设计方法:不同的节点封装不同的操作。

缺点是,节点类型过多,将操作分散在各个节点类中会导致整个系统难以理解、维护和修改。增加新的操作要修改和重新编译所有的类。

改进:节点类独立于作用于其上的操作。

1
将相关操作封装在一个独立的对象(Visitor)中,并在遍历抽象语法树时将此对象传递给当前访问的元素。

2
当一个节点接受一个访问者时,该元素向访问者发送一个包含自身类信息的请求。该请求同时也将该元素本身作为一个参数。

3 访问者将对该元素执行该操作。

适用性:


在下列情况下使用Visitor模式:

一个对象结构包含很多类对象

需要对其中的对象进行很多不同的并且不相关的操作

对象很少改变,经常需要对其上的操作进行修改或新增

需要注意的一点是,如果对象结果和接口经常改变,那么会导致需要重定义所有访问者的接口,会导致很大的代价。所以这种情况还是在对象类中定义操作比较好。

结构:



协作:



示例代码:


背景:假设你的电脑出现问题了
,拿到售后那边检测,售后告诉你必须拆机检测,检测过程通过两个技术人员依次负责不同功能的检测。

分析:本例中,两个负责不同功能检测的技术人员就是Visitor,而电脑的各个部件就是elements。

特点:电脑的部件是固定的,不会有太大的改变,但是如果一种检测方式没有找出问题的话,那么就需要增加检测项。符合访问者模式的特点。

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

//visit.h

#ifndef VISITOR_H

#define VISITOR_H

#include <iostream>

#include <string>

#include <vector>

class
Element;

class
CPU;

class
VideoCard;

class
MainBoard;

/*------------------*/

class
Visitor {

public:

    Visitor(std::string name) {

        visitorName = name;

    }

    virtual
void visitCPU( CPU* cpu ) {};

    virtual
void visitVideoCard( VideoCard* videoCard ) {};

    virtual
void visitMainBoard( MainBoard* mainBoard ) {};

    std::string getName() {

        return
this->visitorName;

    };

private:

    std::string visitorName;

};

class
Element {

public:

    Element( std::string name ) {

        eleName = name;

    }

    virtual
void accept( Visitor* visitor ) {};

    virtual
std::string getName() {

        return
this->eleName;

    }

private:

    std::string eleName;

};

/*----------- Elements -------------*/

class
CPU : public
Element {

public:

    CPU(std::string name) : Element(name) {}

    void
accept(Visitor* visitor) {

        visitor->visitCPU(this);

    }

};

class
VideoCard : public
Element {

public:

    VideoCard(std::string name) : Element(name) {}

    void
accept(Visitor* visitor) {

        visitor->visitVideoCard(this);

    }

};

class
MainBoard : public
Element {

public:

    MainBoard(std::string name) : Element(name) {}

     

    void
accept(Visitor* visitor) {

        visitor->visitMainBoard(this);

    }

};

/*----------- ConcreteVisitor -------------*/

class
CircuitDetector : public
Visitor {

public:

    CircuitDetector(std::string name) : Visitor(name) {}

    // checking cpu

    void
visitCPU( CPU* cpu ) {

        std::cout << Visitor::getName() << " is checking CPU‘s circuits.("
<< cpu->getName()<<")"
<< std::endl;

    }

    // checking videoCard

    void
visitVideoCard( VideoCard* videoCard ) {

        std::cout << Visitor::getName() << " is checking VideoCard‘s circuits.("
<< videoCard->getName()<<")"
<< std::endl;

    }

    // checking mainboard

    void
visitMainBoard( MainBoard* mainboard ) {

        std::cout << Visitor::getName() << " is checking MainBoard‘s circuits.("
<< mainboard->getName() <<")"
<< std::endl;

    }

};

class
FunctionDetector : public
Visitor {

public:

    FunctionDetector(std::string name) : Visitor(name) {}

    virtual
void visitCPU( CPU* cpu ) {

        std::cout << Visitor::getName() << " is check CPU‘s function.("
<< cpu->getName() << ")"<< std::endl;

    }

    // checking videoCard

    void
visitVideoCard( VideoCard* videoCard ) {

        std::cout << Visitor::getName() << " is checking VideoCard‘s function.("
<< videoCard->getName()<< ")"
<< std::endl;

    }

    // checking mainboard

    void
visitMainBoard( MainBoard* mainboard ) {

        std::cout << Visitor::getName() << " is checking MainBoard‘s function.("
<< mainboard->getName() << ")"<< std::endl;

    }

};

/*------------------------*/

class
Computer {

public:

    Computer(CPU* cpu,

            VideoCard* videocard,

            MainBoard* mainboard) {

        elementList.push_back(cpu);

        elementList.push_back(videocard);

        elementList.push_back(mainboard);

    };

    void
Accept(Visitor* visitor) {

        for( std::vector<Element*>::iterator i = elementList.begin(); i != elementList.end(); i++ )

        {

            (*i)->accept(visitor);

        }

    };

private:

    std::vector<Element*> elementList;

};

#endif

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

// main.cpp

#include "visitor.h"

int main() {

    CPU* cpu = new
CPU("Intel CPU");

    VideoCard* videocard = new
VideoCard("XXX video card");

    MainBoard* mainboard = new
MainBoard("HUAWEI mainboard");

    Computer* myComputer = new
Computer(cpu, videocard, mainboard);

    CircuitDetector* Dan = new
CircuitDetector("CircuitDetector Dan");

    FunctionDetector* Tom = new
FunctionDetector("FunctionDetector Tom");

    std::cout << "\nStep 1: Dan is checking computer‘s circuits."
<< std::endl;

    myComputer->Accept(Dan);

    std::cout << "\nStep 2: Tom is checking computer‘s functions."
<< std::endl;

    myComputer->Accept(Tom);

    system("Pause");

    return
0;

}

运行截图:

参考资料:

《设计模式:可复用面向对象软件的基础》

时间: 2024-10-21 23:20:51

设计模式(17) 访问者模式(VISITOR) C++实现的相关文章

设计模式之访问者模式(Visitor)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

【设计模式】—— 访问者模式Visitor

对于某个对象或者一组对象,不同的访问者,产生的结果不同,执行操作也不同.此时,就是访问者模式的典型应用了. 应用场景 1 不同的子类,依赖于不同的其他对象 2 需要对一组对象,进行许多不相关的操作,又不想在类中是现在这些方法 3 定义的类很少改变,但是执行的操作却经常发生改变. 回到顶部 模式结构 Context 环境角色 class Context{ List<Node> list = new ArrayList(); public void add(Node node) { list.ad

[设计模式] 23 访问者模式 visitor Pattern

在GOF的<设计模式:可复用面向对象软件的基础>一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作.访问者模式把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化.该模式的目的是要把处理从数据结构分离出来.访问者模式让增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者.访问者模式将有关的行为集中到一个访问者对象中.   初次接触,定义会显得晦涩并且难于理解,没关系,LZ来陪

设计模式:访问者(Visitor)模式

设计模式:访问者(Visitor)模式 一.前言    什么叫做访问,如果大家学过数据结构,对于这点就很清晰了,遍历就是访问的一般形式,单独读取一个元素进行相应的处理也叫作访问,读取到想要查看的内容+对其进行处理就叫做访问,那么我们平常是怎么访问的,基本上就是直接拿着需要访问的地址(引用)来读写内存就可以了.    为什么还要有一个访问者模式呢,这就要放到OOP之中了,在面向对象编程的思想中,我们使用类来组织属性,以及对属性的操作,那么我们理所当然的将访问操作放到了类的内部,这样看起来没问题,但

设计模式入门之访问者模式Visitor

Set集合的配置 数据表的创建:表关系一个员工拥有多个身份 create table EMPLOYEE ( id INT NOT NULL auto_increment, first_name VARCHAR(20) default NULL, last_name VARCHAR(20) default NULL, salary INT default NULL, PRIMARY KEY (id) ); create table CERTIFICATE ( id INT NOT NULL aut

访问者模式 Visitor 行为型 设计模式(二十七)

访问者模式 Visitor <侠客行>是当代作家金庸创作的长篇武侠小说,新版电视剧<侠客行>中,开篇有一段独白: “茫茫海外,传说有座侠客岛,岛上赏善罚恶二使,每隔十年必到中原武林,向各大门派下发放赏善罚恶令, 强邀掌门人赴岛喝腊八粥,拒接令者,皆造屠戮,无一幸免,接令而去者,杳无音讯,生死未仆,侠客岛之行,已被视为死亡之旅.” 不过话说电视剧,我总是觉得老版的好看. 意图 表示一个作用于某对象结构中的各元素的操作. 它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作.

PHP教程:掌握php设计模式之访问者模式

PHP教程:掌握php设计模式之访问者模式 这篇文章主要帮助大家轻松掌握php设计模式之访问者模式,感兴趣的小伙伴们可以参考一下 访问者模式解决的问题 在我们的代码编写过程当中,经常需要对一些类似的对象添加一些的代码,我们以一个计算机对象打印组成部分为例来看下: /** * 抽象基类 */ abstract class Unit { /** *获取名称 */ abstract public function getName(); } /** * Cpu类 */ class Cpu extends

【设计模式】——访问者模式

访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 访问者模式结构图 访问者模式使用与数据结构相对比较稳定的系统,即数据结构和作用与结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化.其目的,要把处理从数据结构分离开来.很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易.反之,如果这样的

设计模式:访问者模式(Vistor)

访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变.为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的模式动机. 访问者模式即表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 访问者模式适用于数据结构