别院牧志知识库 别院牧志知识库
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2025 面试记录
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2025 面试记录
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 辨析

  • Sockets编程

  • Django

  • stackoverflow

  • Flask

  • 全栈之路

  • 面试

  • 代码片段

  • 异步编程

  • 😎Awesome资源

  • PEP

  • Python工匠系列

  • 高阶知识点

  • Python 学习资源待整理
  • 设计模式

    • Python 设计模式
    • 装饰器模式
    • 抽象工厂模式
    • 建造者模式/生成器模式
    • 原型模式
    • 单例模式
    • 设计模式(2)——工厂方法模式
    • 设计模式(3)——抽象工厂模式
    • 设计模式(4)——模板方法模式
    • 设计模式(5)——代理模式
    • 设计模式(6)——建造者模式
    • 设计模式(7)——策略模式
    • 设计模式(8)——命令模式
    • 设计模式(9)——原型模式
    • 设计模式(10)——中介者模式
    • 设计模式(11)——责任链模式
    • 设计模式(12)——装饰器模式
    • 设计模式(13)——适配器模式
    • 设计模式(14)——迭代器模式
    • 设计模式(15)——观察者模式
    • 设计模式(16)——外观模式
    • 设计模式(17)——状态模式
    • 设计模式(18)——桥接模式
    • 设计模式(19)——享元模式
    • 设计模式(20)——解释器模式
    • 设计模式(21)——组合模式
    • 设计模式(23)——备忘录模式
    • Python 全栈之路系列之单例设计模式
    • 设计模式(22)——访问者模式
      • 基本思想和原则
      • 动机
      • 实现
      • 优点
      • 缺点
    • 工厂方法模式
    • Python 设计模式资源收集
  • 好“艹蛋”的 Python 呀!
  • FIFO | 待学清单📝
  • pip 安装及使用
  • 数据分析

  • 源码阅读计划

  • OOP

  • 关于 python 中的 setup.py
  • 并行分布式框架 Celery
  • 七种武器,让你的代码提高可维护性
  • 使用 pdb 调试 Python 代码
  • 每周一个 Python 标准库
  • 🐍Python
  • 设计模式
佚名
2017-12-22
目录

设计模式(22)——访问者模式

本文介绍访问者模式的概念和应用。

# 基本思想和原则

封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作。

# 动机

如果我们要获取很多类的不同对象的信息时,可以考虑使用访问者模式。这可以将访问类对象信息这个操作和类本身分离。

# 实现

public abstract class Staff {
    private String name;
    private int age;
    private int salary;

    public Staff(String name, int age, int salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getSalary() {
        return this.salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public abstract void accept(IVisitor visitor);
}

public class Empolyee extends Staff {
    private String job;

    public Empolyee(String name, int age, int salary) {
        super(name, age, salary);
    }

    public String getJob() {
        return this.job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

public class Manager extends Staff {
    private int performance;

    public Manager(String name, int age, int salary) {
        super(name, age, salary);
    }

    public int getPerformance() {
        return this.performance;
    }

    public void setPerformance(int performance) {
        this.performance = performance;
    }

    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

public interface IVisitor {
    public void visit(Empolyee empolyee);
    public void visit(Manager manager);
}

    private String info = "";
    @Override
    public void visit(Empolyee empolyee) {
        this.info += this.getBasicInfo(empolyee) + " " + this.getEmpolyeeJob(empolyee) + "\n";
    }

    @Override
    public void visit(Manager manager) {
        this.info += this.getBasicInfo(manager) + " " + this.getManagerPerformance(manager) + "\n";
    }

    private String getBasicInfo(Staff staff) {
        return staff.getName() + " " + staff.getAge() + " " + staff.getSalary();
    }

    private String getEmpolyeeJob(Empolyee empolyee) {
        return empolyee.getJob();
    }

    private int getManagerPerformance(Manager manager) {
        return manager.getPerformance();
    }

    public void showStaffInfo() {
        System.out.println(this.info);
    }
}

public class BonusVisitor implements IVisitor {
    private final static int EMPOLYEE_COEFFICIENT = 2;
    private final static int MANAGER_COEFFICIENT = 4;
    private int totalBonus = 0;

    @Override
    public void visit(Empolyee empolyee) {
        this.totalBonus += empolyee.getSalary() * EMPOLYEE_COEFFICIENT;
    }

    @Override
    public void visit(Manager manager) {
        this.totalBonus += manager.getSalary() * MANAGER_COEFFICIENT;
    }

    public void showTotalBonus() {
        System.out.println("所有人的奖金总和是: " + this.totalBonus);
    }
}

public class Test {
    public static void main(String[] args) {
        InfoVisitor infoVisitor = new InfoVisitor();
        BonusVisitor bonusVisitor = new BonusVisitor();
        for (Staff staff:getStaffs()) {
            staff.accept(infoVisitor);
            staff.accept(bonusVisitor);
        }

        infoVisitor.showStaffInfo();
        bonusVisitor.showTotalBonus();
    }

    private static ArrayList<Staff> getStaffs() {
        ArrayList<Staff> staffs = new  ArrayList<Staff>();

        Empolyee empolyee1 = new Empolyee("Jack", 30, 8000);
        Empolyee empolyee2 = new Empolyee("Bob", 23, 4000);
        Empolyee empolyee3 = new Empolyee("Jane", 33, 9000);
        Manager manager1 = new Manager("John", 50, 20000);

        empolyee1.setJob("Sale");
        empolyee2.setJob("Engineer");
        empolyee3.setJob("Accounting");
        manager1.setPerformance(100000);

        staffs.add(empolyee1);
        staffs.add(empolyee2);
        staffs.add(empolyee3);
        staffs.add(manager1);

        return staffs;
    }
}
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

输出如下:

Jack 30 8000 Sale
Bob 23 4000 Engineer
Jane 33 9000 Accounting
John 50 20000 100000

所有人的奖金总和是: 122000
1
2
3
4
5
6

IVisitor声明了访问者的抽象接口,有两个具体的实现类:InfoVisitor和BonusVisitor,分别负责获取雇员的个人信息和计算奖金,这两个类的职责不同,一个打印信息,一个计算奖金,所以分为两个访问者类来实现没什么问题,实际开发中也提倡这么做。

# 优点

访问者模式符合单一职责原则,被访问者和访问者都可以各自独立发展,互不干扰。扩展性也不错,当需要增加新的访问需求时,只需要增加新的访问者实现类即可。

# 缺点

访问者模式必须了解一个具体类的细节,者违反了迪米特法则。另外有一种情况的扩展比较困难,当我在具体类中加入新的属性时,就需要修改访问者类,如果访问者类比较多,修改量会很大。访问者模式没有依赖抽象,而是依赖具体,这也违反了依赖倒置原则。

编辑 (opens new window)
#设计模式
上次更新: 2024-07-23, 01:00:43
Python 全栈之路系列之单例设计模式
工厂方法模式

← Python 全栈之路系列之单例设计模式 工厂方法模式→

最近更新
01
2025 面试记录
05-28
02
提升沟通亲和力的实用策略
03-26
03
工作
07-15
更多文章>
Theme by Vdoing | Copyright © 2019-2025 IMOYAO | 别院牧志
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式