访问者模式

类图

代码

Element

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
abstract class Medicine{
private String name;
private double price;

public Medicine(String name, double price) {
this.name = name;
this.price = price;
}

public String getName() {
return name;
}

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

public double getPrice() {
return price;
}

public void setPrice(double price) {
this.price = price;
}

public abstract void accept(Visitor visitor);
}

ConcreteElement

1
2
3
4
5
6
7
8
9
10
11
class MedicineA extends Medicine{

public MedicineA(String name, double price) {
super(name, price);
}

@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

Visitor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
abstract class Visitor{
private String name;

public Visitor(String name) {
this.name = name;
}

public String getName() {
return name;
}

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

abstract void visit(Medicine medicine);
}

ConcreteVisitor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Charger extends Visitor{

public Charger(String name) {
super(name);
}

@Override
void visit(Medicine medicine) {
System.out.println("划价员" + getName() + "给药" + medicine.getName() + "划价:" + medicine.getPrice());
}
}

class Worker extends Visitor{

public Worker(String name) {
super(name);
}

@Override
void visit(Medicine medicine) {
System.out.println("药房工作人员" + getName() + "拿药" + medicine.getName());
}
}

ObjectStructure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Presciption{

private List<Medicine> list = new ArrayList<>();

public void accept(Visitor visitor){
for (Medicine medicine : list) {
medicine.accept(visitor);
}
}

public void addMedicine(Medicine medicine){
list.add(medicine);
}

public void removeMedicine(Medicine medicine){
list.remove(medicine);
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main {
public static void main(String args[]){
Medicine medicineA = new MedicineA("板蓝根", 20);
Medicine medicineB = new MedicineA("三九胃泰", 40);

Charger charger = new Charger("小李");
Worker worker = new Worker("小王");

Presciption presciption = new Presciption();

presciption.addMedicine(medicineA);
presciption.addMedicine(medicineB);

presciption.accept(charger);
presciption.accept(worker);

}
}

运行结果

1
2
3
4
划价员小李给药板蓝根划价:20.0
划价员小李给药三九胃泰划价:40.0
药房工作人员小王拿药板蓝根
药房工作人员小王拿药三九胃泰

总结

概述

可以在不改变原有数据结构的情况下定义作用于这些元素的新的操作

优点

增加新的操作很方便,直接加一个新的访问者就可以,无需修改源代码,符合开闭原则
将元素的相关操作都封装在访问者中,更加符合单一职责原则

缺点

增加新元素很难,如果要加新元素,所有访问者都得加一遍访问访问