Golang学习笔记_44——命令模式
Golang学习笔记_45——备忘录模式
Golang学习笔记_46——状态模式
访问者模式是一种行为型设计模式,允许在不修改已有对象结构的前提下定义新的操作。其核心特点包括:
• 操作解耦:将数据操作与数据结构分离
• 双重分发:通过两次方法调用实现动态绑定
• 扩展开放:新增操作无需修改现有类
• 操作污染:频繁添加新操作导致类不断膨胀
• 聚合困难:相关操作分散在不同类中
• 类型检查:避免大量instanceof类型判断
角色 | 作用 |
---|---|
Visitor | 声明访问操作的接口(visit方法) |
ConcreteVisitor | 实现具体访问逻辑 |
Element | 定义接受访问者的接口(accept方法) |
ConcreteElement | 实现accept方法的具体元素 |
ObjectStructure | 包含元素集合的容器 |
@startuml
interface Visitor {
+ visitElementA(e: ElementA)
+ visitElementB(e: ElementB)
}
class TaxVisitor {
+ visitElementA()
+ visitElementB()
}
interface Element {
+ accept(v: Visitor)
}
class ElementA {
+ accept(v: Visitor)
+ operationA()
}
class ElementB {
+ accept(v: Visitor)
+ operationB()
}
Visitor <|.. TaxVisitor
Element <|.. ElementA
Element <|.. ElementB
ElementA ..> Visitor
ElementB ..> Visitor
note right of ElementA::accept
调用visitor.visitElementA(this)
实现双重分派机制
end note
@enduml
优点
缺点
type ASTVisitor interface {
VisitVariableDecl(n *VariableDecl)
VisitFunctionCall(n *FunctionCall)
}
type TypeChecker struct{}
func (t *TypeChecker) VisitVariableDecl(n *VariableDecl) {
fmt.Printf("校验变量 %s 的类型\n", n.Name)
}
type FinancialVisitor interface {
VisitInvoice(i *Invoice)
VisitPayment(p *Payment)
}
type TaxCalculator struct{}
func (t *TaxCalculator) VisitInvoice(i *Invoice) {
fmt.Printf("计算发票税款:%.2f\n", i.Amount*0.1)
}
type UIVisitor interface {
VisitButton(b *Button)
VisitPanel(p *Panel)
}
class Renderer struct{}
func (r *Renderer) VisitButton(b *Button) {
fmt.Printf("渲染按钮:%s\n", b.Label)
}
package visitor_demo
import "fmt"
// Visitor 接口
type ComputerPartVisitor interface {
VisitMouse(m *Mouse)
VisitKeyboard(k *Keyboard)
}
// Concrete Visitor
type DisplayVisitor struct{}
func (d *DisplayVisitor) VisitMouse(m *Mouse) {
fmt.Println("显示鼠标信息:", m.GetSpec())
}
func (d *DisplayVisitor) VisitKeyboard(k *Keyboard) {
fmt.Println("显示键盘信息:", k.GetLayout())
}
// Element 接口
type ComputerPart interface {
Accept(visitor ComputerPartVisitor)
}
// Concrete Elements
type Mouse struct {
dpi int
}
func (m *Mouse) Accept(visitor ComputerPartVisitor) {
visitor.VisitMouse(m)
}
func (m *Mouse) GetSpec() string {
return fmt.Sprintf("%d DPI", m.dpi)
}
type Keyboard struct {
layout string
}
func (k *Keyboard) Accept(visitor ComputerPartVisitor) {
visitor.VisitKeyboard(k)
}
func (k *Keyboard) GetLayout() string {
return k.layout
}
// Object Structure
type Computer struct {
parts []ComputerPart
}
func (c *Computer) AddPart(p ComputerPart) {
c.parts = append(c.parts, p)
}
func (c *Computer) Accept(visitor ComputerPartVisitor) {
for _, p := range c.parts {
p.Accept(visitor)
}
}
// 客户端使用示例
func ExampleUsage() {
computer := &Computer{
parts: []ComputerPart{
&Mouse{dpi: 1600},
&Keyboard{layout: "QWERTY"},
},
}
visitor := &DisplayVisitor{}
computer.Accept(visitor)
}
=== RUN TestExampleUsage
显示鼠标信息: 1600 DPI
显示键盘信息: QWERTY
--- PASS: TestExampleUsage (0.00s)
PASS
type AsyncVisitor interface {
VisitForDB(n Node) <-chan error
VisitForAPI(n Node) <-chan error
}
func BatchVisit(nodes []Node, v AsyncVisitor) []error {
// 实现并发访问处理
}
type DynamicVisitor struct {
handlers map[reflect.Type]func(interface{})
}
func (dv *DynamicVisitor) Register(t reflect.Type, fn func(interface{})) {
dv.handlers[t] = fn
}
模式 | 核心区别 | 典型应用场景 |
---|---|---|
策略模式 | 单算法选择 vs 多元素操作 | 支付方式选择 |
装饰器模式 | 增强功能 vs 添加操作 | IO流处理 |
组合模式 | 树形结构 vs 元素遍历 | 文件系统管理 |
type Visitor interface {
VisitTypeA(*TypeA)
VisitTypeB(*TypeB)
DefaultVisit(interface{})
}
type BaseElement struct{}
func (b *BaseElement) Accept(v Visitor) {
v.DefaultVisit(b)
}
type Element struct {
visitor Visitor `json:"-"` // 避免序列化循环
}
type StatefulVisitor struct {
buffer strings.Builder
}
在Go语言中实现建议: