patternDesign-visitor 新的观察者模式的写法

0 观察者模式的传统写法不再被需要

观察者模式的作用:
核心观点:将 对数据的操作 和 数据本身 做了解耦,新添加数据操作的时候,对数据本身的类不会有任何修改

1 观察者模式实例

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
public class VisitorDemo {
public static void main(final String[] args) {
Car car = new Car();
car.accept(new CarElementPrintVisitor());
}
}
// supertype of all objects in the structure
interface CarElement {
void accept(CarElementVisitor visitor);
}
// supertype of all operations
interface CarElementVisitor {
void visit(Body body);
void visit(Car car);
void visit(Engine engine);
}
class Body implements CarElement {
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Engine implements CarElement {
@Override
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Car implements CarElement {
private final List<CarElement> elements;
public Car() {
this.elements = List.of(new Body(), new Engine());
}
@Override
public void accept(CarElementVisitor visitor) {
for (CarElement element : elements) {
element.accept(visitor);
}
visitor.visit(this);
}
}
class CarElementPrintVisitor implements CarElementVisitor {
@Override
public void visit(Body body) {
System.out.println("Visiting body");
}
@Override
public void visit(Car car) {
System.out.println("Visiting car");
}
@Override
public void visit(Engine engine) {
System.out.println("Visiting engine");
}
}

2 利用封装接口和类型switch特性(java17) 快速达到目标

代码少了一半,但是效果确完全相同

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
public class VisitorDemo {
public static void main(final String[] args) {
Car car = new Car();
print(car);
}
// 这就是visitor
private static void print(Car car) {
car.elements()
.map(element -> switch (element) {
case Body body -> "Visiting body";
case Car car_ -> "Visiting car";
case Engine engine -> "Visiting engine";
})
.forEach(System.out::println);
}
}
// supertype of all objects in the structure
sealed interface CarElement
permits Body, Engine, Car { }
class Body implements CarElement { }
class Engine implements CarElement { }
class Car implements CarElement {
private final List<CarElement> elements;
public Car() {
this.elements = List.of(new Body(), new Engine());
}
public Stream<CarElement> elements() {
return Stream.concat(elements.stream(), Stream.of(this));
}
}

使用注意:
使结构类型的接口密封 (你不应修改密封接口,若要修改,参见3)
对于操作,使用模式开关来确定每种类型的代码路径 (从switch到具体的类的类型)
避免使用默认分支,这样当你修改类型接口时,你才能获得在每个switch中出现编译错误,这可以引导你去修改