访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。

使用场景

  1. 对象结构稳定,但需要新增操作:当一个对象结构中的元素类很少变化,但是需要经常添加新的操作时,访问者模式就可以派上用场。通过将新操作封装在访问者中,可以避免修改元素类并保持系统的稳定性。

  2. 元素类的职责不应该包含所有操作:有时候,为了遵循单一职责原则,我们不希望在元素类中包含太多操作。访问者模式可以将对元素的不同操作分离出来,使得每个类只负责自己的职责。

  3. 操作需要访问不同类型的元素:如果系统中存在多种不同类型的元素,并且需要执行不同的操作,但不希望在每个元素类中都包含这些操作的实现,那么访问者模式可以提供一个统一的方式来处理这些操作。

  4. 数据结构稳定,但经常需要新增操作:当数据结构相对稳定,但需要不断新增操作时,访问者模式可以减少修改现有代码的需要,因为新增操作只需要添加一个新的访问者类。

  5. 数据结构与操作分离:访问者模式可以有效地将数据结构与操作分离,使得系统更加灵活和易于扩展。这样可以使得数据结构的变化和操作的变化相互独立。

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
package main

import "fmt"

// Shape 接口定义了图形对象的行为
type Shape interface {
accept(Visitor)
}

// Circle 圆形
type Circle struct{}

func (c *Circle) accept(v Visitor) {
v.visitCircle(c)
}

// Rectangle 矩形
type Rectangle struct{}

func (r *Rectangle) accept(v Visitor) {
v.visitRectangle(r)
}

// Visitor 定义了访问者接口
type Visitor interface {
visitCircle(*Circle)
visitRectangle(*Rectangle)
}

// AreaCalculator 计算图形面积的访问者
type AreaCalculator struct {
totalArea float64
}

func (ac *AreaCalculator) visitCircle(c *Circle) {
fmt.Println("计算圆形面积")
// 假设这里有圆形面积的计算逻辑
ac.totalArea += 3.14 // 假设圆的面积计算逻辑
}

func (ac *AreaCalculator) visitRectangle(r *Rectangle) {
fmt.Println("计算矩形面积")
// 假设这里有矩形面积的计算逻辑
ac.totalArea += 10 // 假设矩形的面积计算逻辑
}

func main() {
// 创建图形对象
circle := &Circle{}
rectangle := &Rectangle{}

// 创建访问者
areaCalculator := &AreaCalculator{}

// 计算圆形面积
circle.accept(areaCalculator)

// 计算矩形面积
rectangle.accept(areaCalculator)

// 输出总面积
fmt.Printf("总面积:%f\n", areaCalculator.totalArea)
}

结语

访问者模式通过将操作抽象成访问者,并将访问者与元素类分离,访问者模式使得系统更加易于扩展和维护。


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。