访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。
使用场景
对象结构稳定,但需要新增操作:当一个对象结构中的元素类很少变化,但是需要经常添加新的操作时,访问者模式就可以派上用场。通过将新操作封装在访问者中,可以避免修改元素类并保持系统的稳定性。
元素类的职责不应该包含所有操作:有时候,为了遵循单一职责原则,我们不希望在元素类中包含太多操作。访问者模式可以将对元素的不同操作分离出来,使得每个类只负责自己的职责。
操作需要访问不同类型的元素:如果系统中存在多种不同类型的元素,并且需要执行不同的操作,但不希望在每个元素类中都包含这些操作的实现,那么访问者模式可以提供一个统一的方式来处理这些操作。
数据结构稳定,但经常需要新增操作:当数据结构相对稳定,但需要不断新增操作时,访问者模式可以减少修改现有代码的需要,因为新增操作只需要添加一个新的访问者类。
数据结构与操作分离:访问者模式可以有效地将数据结构与操作分离,使得系统更加灵活和易于扩展。这样可以使得数据结构的变化和操作的变化相互独立。
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"
type Shape interface { accept(Visitor) }
type Circle struct{}
func (c *Circle) accept(v Visitor) { v.visitCircle(c) }
type Rectangle struct{}
func (r *Rectangle) accept(v Visitor) { v.visitRectangle(r) }
type Visitor interface { visitCircle(*Circle) visitRectangle(*Rectangle) }
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) }
|
结语
访问者模式通过将操作抽象成访问者,并将访问者与元素类分离,访问者模式使得系统更加易于扩展和维护。