[go] 访问者模式

访问者模式

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

模型说明

  1. 访问者(Visitor)接口声明了一系列以对象结构的具体元素为参数的访问者方法。如果编程语言支持重载,这些方法的名称可以是相同的,但是其参数一定是不同的。
  2. 具体访问者(Concrete Visitor)会为不同的具体元素类实现相同行为的几个不同版本。
  3. 元素(Element)接口声明了一个方法来"接收"访问者。该方法必须有一个参数被声明为访问者接口类型。
  4. 具体元素(Concrete Element)必须实现接收方法。该方法的目的是根据当前元素类将其调用重定向到相应访问者的方法。请注意,即使元素基类实现了该方法,所有子类都必须对其进行重写并调用访问者对象中的合适方法。
  5. 客户端(Client)通常会作为集合或其他复杂对象(例如一个组合树)的代表。客户端通常不知晓所有的具体元素类,因为它们会通过抽象接口与集合中的对象进行交互。

优缺点

1.优点

  • *开闭原则:*你可以引入在不同类对象上执行的新行为,且无需对这些类做出修改。
  • *单一职责原则:*可将同一行为的不同版本移到同一个类中。
  • 访问者对象可以在与各种对象交互时收集一些有用的信息。当你想要遍历一些复杂的对象结构(例如对象树),并在结构中的每个对象上应用访问者时,这些信息可能会有所帮助。

2.缺点

  • 每次在元素层次结构中添加或移除一个类时,你都要更新所有的访问者。
  • 在访问者同某个元素进行交互时,它们可能没有访问元素私有成员变量和方法的必要权限。

使用场景

如果你需要对一个复杂对象结构(例如对象树)中的所有元素执行某些操作,可使用访问者模式。

可使用访问者模式来清理辅助行为的业务逻辑。

当某个行为仅在类层次结构中的一些类中有意义,而在其他类中没有意义时,可使用该模式。

参考代码

shape.go: 元件

go 复制代码
package main

type Shape interface {
	getType() string
	accept(Visitor)
}

square.go: 具体元件

go 复制代码
package main

type Square struct {
    side int
}

func (s *Square) accept(v Visitor) {
    v.visitForSquare(s)
}

func (s *Square) getType() string {
    return "Square"
}

circle.go: 具体元件

go 复制代码
package main

type Circle struct {
    radius int
}

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

func (c *Circle) getType() string {
    return "Circle"
}

rectangle.go: 具体元件

go 复制代码
package main

type Rectangle struct {
    l int
    b int
}

func (t *Rectangle) accept(v Visitor) {
    v.visitForrectangle(t)
}

func (t *Rectangle) getType() string {
    return "rectangle"
}

visitor.go: 访问者

go 复制代码
package main

type Visitor interface {
    visitForSquare(*Square)
    visitForCircle(*Circle)
    visitForRectangle(*Rectangle)
}

areaCalculator.go: 具体访问者

go 复制代码
package main

import (
    "fmt"
)

type AreaCalculator struct {
    area int
}

func (a *AreaCalculator) visitForSquare(s *Square) {
    // Calculate area for square.
    // Then assign in to the area instance variable.
    fmt.Println("Calculating area for square")
}

func (a *AreaCalculator) visitForCircle(s *Circle) {
    fmt.Println("Calculating area for circle")
}
func (a *AreaCalculator) visitForRectangle(s *Rectangle) {
    fmt.Println("Calculating area for rectangle")
}

middleCoordinates.go: 具体访问者

go 复制代码
package main

import "fmt"

type MiddleCoordinates struct {
    x int
    y int
}

func (a *MiddleCoordinates) visitForSquare(s *Square) {
    // Calculate middle point coordinates for square.
    // Then assign in to the x and y instance variable.
    fmt.Println("Calculating middle point coordinates for square")
}

func (a *MiddleCoordinates) visitForCircle(c *Circle) {
    fmt.Println("Calculating middle point coordinates for circle")
}
func (a *MiddleCoordinates) visitForRectangle(t *Rectangle) {
    fmt.Println("Calculating middle point coordinates for rectangle")
}

main.go: 客户端代码

go 复制代码
package main

import "fmt"

func main() {
    square := &Square{side: 2}
    circle := &Circle{radius: 3}
    rectangle := &Rectangle{l: 2, b: 3}

    areaCalculator := &AreaCalculator{}

    square.accept(areaCalculator)
    circle.accept(areaCalculator)
    rectangle.accept(areaCalculator)

    fmt.Println()
    middleCoordinates := &MiddleCoordinates{}
    square.accept(middleCoordinates)
    circle.accept(middleCoordinates)
    rectangle.accept(middleCoordinates)
}

output:

go 复制代码
Calculating area for square
Calculating area for circle
Calculating area for rectangle

Calculating middle point coordinates for square
Calculating middle point coordinates for circle
Calculating middle point coordinates for rectangle
相关推荐
神仙别闹8 小时前
基于 C++ 实现(控制台)学生成绩管理系统
开发语言·c++
伞伞悦读9 小时前
【第36期】Python 目录与路径详解:pathlib、文件遍历、创建、复制、移动和删除风险
开发语言·python
名字还没想好☜10 小时前
Go context.AfterFunc 实战(Go 1.21):context 一取消就自动跑清理,告别手写 goroutine 监听 Done
后端·golang·go
web守墓人11 小时前
【goed/ui】自定义组件设计思想篇
linux·windows·ui·golang
2601_9669496511 小时前
只拿到股票代码还不够:量化程序到底还需要哪些标的信息?——从数据建模开始理解股票元数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
m0_7345717612 小时前
深入理解5g <十八>传输块tbsize的计算
开发语言·5g
RAN114267600813 小时前
1.3第一个程序的介绍
开发语言·qt
blue_ice .14 小时前
Verilog DDS 数字信号发生器:DAC 输出模拟波形与 ADC 回采观测
开发语言·单片机·嵌入式硬件·fpga开发
远翔调光芯片^1382879887214 小时前
ECP5702能芯科技PD取电芯片在市场上的优势有哪些?
开发语言·人工智能·单片机·嵌入式硬件·智能家居
泡海椒15 小时前
规则引擎对比:JQuick-Java vs Drools 轻量场景选型对比
java·开发语言