一、简介
访问者模式允许一个或者多个操作应用到一组对象上,设计意图是解耦操作和对象本身,保持类职责单一、满足开闭原则以及应对代码的复杂性。
二、优点
- 分离操作和数据结构
- 增加新操作更容易
- 集中化操作
三、适用场景
- 数据结构稳定,操作易变
- 一个对象的操作之间无关联
四、UML类图
五、案例
有圆形和矩形两种对象,有画图和调整大小两种数据访问者对形状进行处理。
package main
import "fmt"
type Shape interface {
Accept(visitor Visitor)
GetType() string
}
type Circle struct {
}
func NewCircle() *Circle {
return &Circle{}
}
func (c *Circle) Accept(visitor Visitor) {
visitor.Visit(c)
}
func (c *Circle) GetType() string {
return "Circle"
}
type Rectangle struct {
}
func NewRectangle() *Rectangle {
return &Rectangle{}
}
func (r *Rectangle) Accept(visitor Visitor) {
visitor.Visit(r)
}
func (r *Rectangle) GetType() string {
return "Rectangle"
}
type Visitor interface {
Visit(shape Shape)
}
type DrawVisitor struct {
}
func NewDrawVisitor() *DrawVisitor {
return &DrawVisitor{}
}
func (dv *DrawVisitor) Visit(shape Shape) {
if shape.GetType() == "Circle" {
fmt.Println("Drawing a circle")
} else if shape.GetType() == "Rectangle" {
fmt.Println("Drawing a rectangle")
} else {
fmt.Println("Unknown shape")
}
}
type ResizeVisitor struct {
}
func NewResizeVisitor() *ResizeVisitor {
return &ResizeVisitor{}
}
func (rv *ResizeVisitor) Visit(shape Shape) {
if shape.GetType() == "Circle" {
fmt.Println("Resizing a circle")
} else if shape.GetType() == "Rectangle" {
fmt.Println("Resizing a rectangle")
} else {
fmt.Println("Unknown shape")
}
}
func main() {
circle := NewCircle()
rectangle := NewRectangle()
drawVisitor := NewDrawVisitor()
resizeVisitor := NewResizeVisitor()
circle.Accept(drawVisitor)
circle.Accept(resizeVisitor)
rectangle.Accept(drawVisitor)
rectangle.Accept(resizeVisitor)
}