行为型设计模式之访问者模式:
一、含义
访问者(一个类)访问到(接收到)各种元素(各种类)后作出相应的操作
(针对访问的对象不同(意味着可访问多个不同的对象),执行不同的操作)
二、代码说明
1.主要有两个角色
1)访问者:
访问到各个类后,对应各个类该怎么干,要做什么事情。
2)元素:
允许接受哪一类访问者访问(调用该访问者作出相应的操作),当然也有自己的业务逻辑
2.在用C实现过程中也是参考这种思想,以各种员工通过各自的访问者获得各自的信息报表举例,具体实现如下:
1)访问者模式使用场景:
VisitorPatternUsage.c
2)被调用者:
1 /*****************************************************************************
2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved.
3 ------------------------------------------------------------------------------
4 * File Module : VisitorPattern.c
5 * Description : 访问者模式
6 本文件是被访问者的实现
7 以各种员工通过各自的访问者获得各自的
8 信息举例
9
10 * Created : 2017.07.17.
11 * Author : Yu Weifeng
12 * Function List :
13 * Last Modified :
14 * History :
15 ******************************************************************************/
16 #include"stdio.h"
17 #include"malloc.h"
18 #include"stdlib.h"
19 #include"string.h"
20 #include"VisitorPattern.h"
21
22 /*****************************************************************************
23 -Fuction : ManagerVisitor
24 -Description : 公有函数
25 -Input :
26 -Output :
27 -Return :
28 * Modify Date Version Author Modification
29 * -----------------------------------------------
30 * 2017/07/17 V1.0.0 Yu Weifeng Created
31 ******************************************************************************/
32 void ManagerVisitor(T_Manager *ptManagerEmployee)
33 {
34 printf("姓名:%s, 薪水:%d\r\n绩效:%s\r\n",ptManagerEmployee->tEmployee.GetName(&ptManagerEmployee->tEmployee),
35 ptManagerEmployee->tEmployee.GetSalary(&ptManagerEmployee->tEmployee),ptManagerEmployee->GetPerformance(&ptManagerEmployee->tEmployee));
36
37 }
38
39 /*****************************************************************************
40 -Fuction : CommonEmployeeVisitor
41 -Description : 公有函数
42 -Input :
43 -Output :
44 -Return :
45 * Modify Date Version Author Modification
46 * -----------------------------------------------
47 * 2017/07/17 V1.0.0 Yu Weifeng Created
48 ******************************************************************************/
49 void CommonEmployeeVisitor(T_CommonEmployee *ptEmployee)
50 {
51 printf("姓名:%s, 薪水:%d\r\n工作:%s\r\n",ptEmployee->tEmployee.GetName(&ptEmployee->tEmployee),
52 ptEmployee->tEmployee.GetSalary(&ptEmployee->tEmployee),ptEmployee->GetJobContent(&ptEmployee->tEmployee));
53
54 }
VisitorPattern.c
1 /*****************************************************************************
2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved.
3 ------------------------------------------------------------------------------
4 * File Module : VisitorPattern.h
5 * Description : 访问者模式
6
7 * Created : 2017.07.17.
8 * Author : Yu Weifeng
9 * Function List :
10 * Last Modified :
11 * History :
12 ******************************************************************************/
13 #ifndef VISITOR_PATTERN_H
14 #define VISITOR_PATTERN_H
15
16 struct Employee;
17 struct Manager;
18 struct CommonEmployee;
19
20 typedef struct Visitor//访问者类
21 {//C不好实现重载,暂时用定义多个的形式
22 void (*ManagerVisit)(struct Manager *ptEmployee);//访问函数
23 void (*CommonEmployeeVisit)(struct CommonEmployee *ptEmployee);//访问函数
24
25 //void (*Visit)(struct Employee *ptEmployee);//访问函数
26 }T_Visitor;//接口
27
28 typedef struct Employee
29 {
30 char *strName;//因为各个对象需要各自的空间,所以,不得已,私有数据成员放这里
31 int iSalary;//但是为保证不直接访问私有的数据成员,人为约定,访问只能通过公有函数
32 char *(*GetName)(struct Employee *ptThis);//具体函数(本层实现)
33 void (*SetName)(struct Employee *ptThis,char *i_strName);//具体函数(本层实现)
34 int (*GetSalary)(struct Employee *ptThis);//具体函数(本层实现)
35 void (*SetSalary)(struct Employee *ptThis,int i_iSalary);//具体函数(本层实现)
36 //允许的访问者,可选择具体哪个访问者//函数内部对传入参数指针强制转换
37 void (*Accept)(struct Employee *ptThis,T_Visitor i_tAcceptVisitor);//抽象函数(下一层实现)
38 }T_Employee;//员工抽象类
39
40 typedef struct CommonEmployee
41 {
42 T_Employee tEmployee;
43 char *(*GetJobContent)();//具体函数(本层实现)
44 void (*SetJobContent)(char *i_strJobContent);//具体函数(本层实现)
45 }T_CommonEmployee;
46
47 typedef struct Manager
48 {
49 T_Employee tEmployee;
50 char *(*GetPerformance)();//具体函数(本层实现)
51 void (*SetPerformance)(char *i_strPerformance);//具体函数(本层实现)
52 }T_Manager;
53
54
55
56 void ManagerVisitor(T_Manager *ptEmployee);
57 void CommonEmployeeVisitor(T_CommonEmployee *ptEmployee);
58 #define newVisitor {ManagerVisitor,CommonEmployeeVisitor}
59
60
61 char * EmployeeGetName(T_Employee *ptThis);
62 void EmployeeSetName(T_Employee *ptThis,char *i_strName);
63 int EmployeeGetSalary(T_Employee *ptThis);
64 void EmployeeSetSalary(T_Employee *ptThis,int i_iSalary);
65
66 void ManagerAccept(T_Employee *ptThis,T_Visitor i_tAcceptVisitor);
67 char * ManagerGetPerformance();
68 void ManagerSetPerformance(char *i_strPerformance);
69 //宏定义里面内容不可修改
70 #define newManager {NULL,0,EmployeeGetName,EmployeeSetName,EmployeeGetSalary,EmployeeSetSalary,\
71 ManagerAccept,ManagerGetPerformance,ManagerSetPerformance}
72
73 void CommonEmployeeAccept(T_Employee *ptThis,T_Visitor i_tAcceptVisitor);
74 char * CommonEmployeeGetJobContent();
75 void CommonEmployeeSetJobContent(char *i_strJobContent);
76 //宏定义里面内容不可修改
77 #define newCommonEmployee {NULL,0,EmployeeGetName,EmployeeSetName,EmployeeGetSalary,EmployeeSetSalary,\
78 CommonEmployeeAccept,CommonEmployeeGetJobContent,CommonEmployeeSetJobContent}
79
80 #endif
VisitorPattern.h
1 /*****************************************************************************
2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved.
3 ------------------------------------------------------------------------------
4 * File Module : Employee.c
5 * Description : 员工
6 本文件是员工实现类具体的动作
7 * Created : 2017.07.17.
8 * Author : Yu Weifeng
9 * Function List :
10 * Last Modified :
11 * History :
12 ******************************************************************************/
13 #include"stdio.h"
14 #include"malloc.h"
15 #include"stdlib.h"
16 #include"string.h"
17 #include"VisitorPattern.h"
18
19 /*****************************************************************************
20 -Fuction : EmployeeGetName
21 -Description : 公有函数
22 -Input :
23 -Output :
24 -Return :
25 * Modify Date Version Author Modification
26 * -----------------------------------------------
27 * 2017/07/17 V1.0.0 Yu Weifeng Created
28 ******************************************************************************/
29 char * EmployeeGetName(T_Employee *ptThis)
30 {
31 return ptThis->strName;
32 }
33 /*****************************************************************************
34 -Fuction : EmployeeSetName
35 -Description : 公有函数
36 -Input :
37 -Output :
38 -Return :
39 * Modify Date Version Author Modification
40 * -----------------------------------------------
41 * 2017/07/17 V1.0.0 Yu Weifeng Created
42 ******************************************************************************/
43 void EmployeeSetName(T_Employee *ptThis,char *i_strName)
44 {
45 ptThis->strName=i_strName;
46 }
47
48 /*****************************************************************************
49 -Fuction : EmployeeGetSalary
50 -Description : 公有函数
51 -Input :
52 -Output :
53 -Return :
54 * Modify Date Version Author Modification
55 * -----------------------------------------------
56 * 2017/07/17 V1.0.0 Yu Weifeng Created
57 ******************************************************************************/
58 int EmployeeGetSalary(T_Employee *ptThis)
59 {
60 return ptThis->iSalary;
61 }
62
63 /*****************************************************************************
64 -Fuction : EmployeeSetSalary
65 -Description : 公有函数
66 -Input :
67 -Output :
68 -Return :
69 * Modify Date Version Author Modification
70 * -----------------------------------------------
71 * 2017/07/17 V1.0.0 Yu Weifeng Created
72 ******************************************************************************/
73 void EmployeeSetSalary(T_Employee *ptThis,int i_iSalary)
74 {
75 ptThis->iSalary=i_iSalary;
76 }
Employee.c
1 /*****************************************************************************
2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved.
3 ------------------------------------------------------------------------------
4 * File Module : Manager.c
5 * Description : 经理(管理类员工)
6 本文件是经理实现类具体的动作
7 * Created : 2017.07.13.
8 * Author : Yu Weifeng
9 * Function List :
10 * Last Modified :
11 * History :
12 ******************************************************************************/
13 #include"stdio.h"
14 #include"malloc.h"
15 #include"stdlib.h"
16 #include"string.h"
17 #include"VisitorPattern.h"
18
19
20
21
22 static char *g_strPerformance="零";
23
24 /*****************************************************************************
25 -Fuction : ManagerGetPerformance
26 -Description : 获取绩效
27 -Input :
28 -Output :
29 -Return :
30 * Modify Date Version Author Modification
31 * -----------------------------------------------
32 * 2017/07/17 V1.0.0 Yu Weifeng Created
33 ******************************************************************************/
34 char * ManagerGetPerformance()
35 {
36 return g_strPerformance;
37 }
38
39 /*****************************************************************************
40 -Fuction : ManagerSetPerformance
41 -Description :
42 -Input :
43 -Output :
44 -Return :
45 * Modify Date Version Author Modification
46 * -----------------------------------------------
47 * 2017/07/17 V1.0.0 Yu Weifeng Created
48 ******************************************************************************/
49 void ManagerSetPerformance(char *i_strPerformance)
50 {
51 g_strPerformance=i_strPerformance;
52 }
53
54 /*****************************************************************************
55 -Fuction : ManagerAccept
56 -Description :
57 -Input :
58 -Output :
59 -Return :
60 * Modify Date Version Author Modification
61 * -----------------------------------------------
62 * 2017/07/17 V1.0.0 Yu Weifeng Created
63 ******************************************************************************/
64 void ManagerAccept(T_Employee *ptThis,T_Visitor i_tAcceptVisitor)
65 {
66 i_tAcceptVisitor.ManagerVisit((T_Manager *)ptThis);
67 }
Manager.c
1 /*****************************************************************************
2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved.
3 ------------------------------------------------------------------------------
4 * File Module : CommonEmployee.c
5 * Description : 普通员工(普通类员工)
6 本文件是普通员工实现类具体的动作
7 * Created : 2017.07.17.
8 * Author : Yu Weifeng
9 * Function List :
10 * Last Modified :
11 * History :
12 ******************************************************************************/
13 #include"stdio.h"
14 #include"malloc.h"
15 #include"stdlib.h"
16 #include"string.h"
17 #include"VisitorPattern.h"
18
19
20 static char *g_strJobContent="无";
21
22 /*****************************************************************************
23 -Fuction : CommonEmployeeGetJobContent
24 -Description : 获取绩效
25 -Input :
26 -Output :
27 -Return :
28 * Modify Date Version Author Modification
29 * -----------------------------------------------
30 * 2017/07/17 V1.0.0 Yu Weifeng Created
31 ******************************************************************************/
32 char * CommonEmployeeGetJobContent()
33 {
34 return g_strJobContent;
35 }
36
37 /*****************************************************************************
38 -Fuction : CommonEmployeeSetJobContent
39 -Description :
40 -Input :
41 -Output :
42 -Return :
43 * Modify Date Version Author Modification
44 * -----------------------------------------------
45 * 2017/07/17 V1.0.0 Yu Weifeng Created
46 ******************************************************************************/
47 void CommonEmployeeSetJobContent(char *i_strJobContent)
48 {
49 g_strJobContent=i_strJobContent;
50 }
51
52 /*****************************************************************************
53 -Fuction : CommonEmployeeAccept
54 -Description :
55 -Input :
56 -Output :
57 -Return :
58 * Modify Date Version Author Modification
59 * -----------------------------------------------
60 * 2017/07/17 V1.0.0 Yu Weifeng Created
61 ******************************************************************************/
62 void CommonEmployeeAccept(T_Employee *ptThis,T_Visitor i_tAcceptVisitor)
63 {
64 i_tAcceptVisitor.CommonEmployeeVisit((T_CommonEmployee *)ptThis);
65 }
CommonEmployee.c
3)执行结果:
book@book-desktop:/work/projects/test/DesignPatterns/VisitorPattern$ gcc -o VisitorPatternUsage CommonEmployee.c Employee.c Manager.c VisitorPattern.c VisitorPatternUsage.c
book@book-desktop:/work/projects/test/DesignPatterns/VisitorPattern$ ./VisitorPatternUsage
姓名:张三, 薪水:50000
绩效:基本上为负,但是会拍领导马屁啊
姓名:李四, 薪水:15000
工作:编写程序,苦逼的搬运工
4)详细代码:
三、使用场景
1.业务规则要求遍历多个不同的对象是,一定要考虑使用访问者模式。
这本身也是访问者模式出发点,迭代器模式只能访问(遍历)同类或同接口的数据(当然了,如果你是用instanceof,那么能访问所有的数据,这没有争论),而访问者模式是对迭代器模式的扩充,可以遍历不同的对象,然后执行不同的操作,也就是针对访问的对象不同,执行不同的操作。
2.访问者模式还有一个用途,就是充当拦截器角色
3.访问者模式是一种集中规整模式,可以很容易把一些功能进行梳理,达到最终目的---功能集中化,如一个统一的报表运算,UI展现等。
四、优点
1.符合单一职责原则
具体元素角色也就是Employee抽象类的两个子类负责数据的加载,而访问者visitor类则负责报表的展现,两个不同的职责非常明确地分离开来
2.优秀的扩展性
由于职责分开,继续增加对数据的操作是非常快捷的,例如现在要增加一份给老板的报表,这份报表格式又有所不同,直接在Visitor中增加一个方法,传递数据后进行整理打印
3.灵活性非常高
数据由访问者处理,修改访问者就能得到相应的处理
五、缺点
1.具体元素对访问者公布细节
访问者要访问一个类就必然要求这个类公布一些方法和数据,也就是访问者关注了其他类的内部细节,这时迪米特法则所不建议的。
2.具体元素变更比较困难
具体元素角色的增加,删除,修改都比较困难,就上面那个例子,想增加一个成员变量,如年龄age,Visitor就需要修改,如果Visitor是一个还好办,多个呢?业务逻辑再复杂点呢?
3.违背了依赖倒置原则
访问者依赖的具体元素,而不是抽象元素,这破坏了依赖倒置原则,特别是在面向对象的编程中,抛弃了对接口的依赖,而直接依赖实现类,扩展比较难。
六、访问者模式扩展
1.多个访问者的情况
再另外定义访问者即可,使用的时候由具体元素允许其访问(调用该访问者)
七、几种设计模式总结附图(仅供参考)