设计模式之访问者模式20170718

行为型设计模式之访问者模式:

一、含义

访问者(一个类)访问到(接收到)各种元素(各种类)后作出相应的操作

(针对访问的对象不同(意味着可访问多个不同的对象),执行不同的操作)

 

二、代码说明

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)详细代码:

https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/BehavioralDesignPatterns/VisitorPattern

 

三、使用场景

1.业务规则要求遍历多个不同的对象是,一定要考虑使用访问者模式。

这本身也是访问者模式出发点,迭代器模式只能访问(遍历)同类或同接口的数据(当然了,如果你是用instanceof,那么能访问所有的数据,这没有争论),而访问者模式是对迭代器模式的扩充,可以遍历不同的对象,然后执行不同的操作,也就是针对访问的对象不同,执行不同的操作。

2.访问者模式还有一个用途,就是充当拦截器角色

3.访问者模式是一种集中规整模式,可以很容易把一些功能进行梳理,达到最终目的---功能集中化,如一个统一的报表运算,UI展现等。

 

四、优点

1.符合单一职责原则

具体元素角色也就是Employee抽象类的两个子类负责数据的加载,而访问者visitor类则负责报表的展现,两个不同的职责非常明确地分离开来

2.优秀的扩展性

由于职责分开,继续增加对数据的操作是非常快捷的,例如现在要增加一份给老板的报表,这份报表格式又有所不同,直接在Visitor中增加一个方法,传递数据后进行整理打印

3.灵活性非常高

数据由访问者处理,修改访问者就能得到相应的处理

 

五、缺点

1.具体元素对访问者公布细节

访问者要访问一个类就必然要求这个类公布一些方法和数据,也就是访问者关注了其他类的内部细节,这时迪米特法则所不建议的。

2.具体元素变更比较困难

具体元素角色的增加,删除,修改都比较困难,就上面那个例子,想增加一个成员变量,如年龄age,Visitor就需要修改,如果Visitor是一个还好办,多个呢?业务逻辑再复杂点呢?

3.违背了依赖倒置原则

访问者依赖的具体元素,而不是抽象元素,这破坏了依赖倒置原则,特别是在面向对象的编程中,抛弃了对接口的依赖,而直接依赖实现类,扩展比较难。

 

六、访问者模式扩展

1.多个访问者的情况

再另外定义访问者即可,使用的时候由具体元素允许其访问(调用该访问者)

 

七、几种设计模式总结附图(仅供参考)

posted @ 2017-07-18 19:42  yuweifeng  阅读(269)  评论(0编辑  收藏  举报