什么是访问者模式

访问者模式

来看一个golang语言的例子

20201124185545

  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
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
package main

import (
	"fmt"
)

type shape interface {
	getType() string
	accept(visitor)
}

type square struct {
	side int
}
func (s *square) accept(v visitor) {
	v.visitForSquare(s)
}
func (s *square) getType() string {
	return "Square"
}

// --------------------------------------------

type circle struct {
	radius int
}
func (c *circle) accept(v visitor) {
	v.visitForCircle(c)
}
func (c *circle) getType() string {
	return "Circle"
}

// --------------------------------------------

type rectangle struct {
	l int
	b int
}
func (t *rectangle) accept(v visitor) {
	v.visitForrectangle(t)
}
func (t *rectangle) getType() string {
	return "rectangle"
}

// --------------------------------------------

type visitor interface {
	visitForSquare(*square)
	visitForCircle(*circle)
	visitForrectangle(*rectangle)
}

type areaCalculator struct {
	area int
}
func (a *areaCalculator) visitForSquare(s *square) {
	//Calculate area for square. After calculating the area assign in to the area instance variable
	fmt.Printf("Calculating area for square; %p", s)
	fmt.Println()
}
func (a *areaCalculator) visitForCircle(s *circle) {
	//Calculate are for circle. After calculating the area assign in to the area instance variable
	fmt.Printf("Calculating area for circle; %p", s)
	fmt.Println()
}
func (a *areaCalculator) visitForrectangle(s *rectangle) {
	//Calculate are for rectangle. After calculating the area assign in to the area instance variable
	fmt.Printf("Calculating area for rectangle; %p", s)
	fmt.Println()
}

type middleCoordinates struct {
	x int
	y int
}
func (a *middleCoordinates) visitForSquare(s *square) {
	//Calculate middle point coordinates for square. After calculating the area assign in to the x and y instance variable.
	fmt.Println("Calculating middle point coordinates for square")
	fmt.Println()
}
func (a *middleCoordinates) visitForCircle(c *circle) {
	//Calculate middle point coordinates for square. After calculating the area assign in to the x and y instance variable.
	fmt.Println("Calculating middle point coordinates for circle")
	fmt.Println()
}
func (a *middleCoordinates) visitForrectangle(t *rectangle) {
	//Calculate middle point coordinates for square. After calculating the area assign in to the x and y instance variable.
	fmt.Println("Calculating middle point coordinates for rectangle")
	fmt.Println()
}

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

	areaCalculator := &areaCalculator{}
	s.accept(areaCalculator)
	circle.accept(areaCalculator)
	rectangle.accept(areaCalculator)

	fmt.Println()

	middleCoordinates := &middleCoordinates{}
	s.accept(middleCoordinates)
	circle.accept(middleCoordinates)
	rectangle.accept(middleCoordinates)
})
}

访问者模式的变体

如果访问的是一个类型,但是有多个访问者,访问类型的不同部分,那么可以使用次变体.

函数的参数也是函数;也就是一直传递的是函数,那么一套一套,最终肯定是要执行(可以在任意层执行,当然这里是最后一环执行。).

 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
65
66
67
68
69
70
71
72
73
package main

import (
	"fmt"
)

type square struct {
	side int
}

// -------------------------------------------------------------------------------------------------

type IVisitor interface{
	visitor(ViewObjectFooSignation) error
}

//type ViewObjectFooSignation = func (iVisitor IVisitor)error

// one object, but multi-visitor
type ViewObjectFooSignation = func (*square)error
func (s *square) visitor(foo ViewObjectFooSignation)error{
	return foo(s)
}

type Visitor1 struct{
	iVisitor IVisitor
}
// 函数的参数也是函数;也就是一直传递的是函数,那么一套一套,最终肯定是要执行(可以在任意层执行,当然这里是最后一环执行。)
func (v *Visitor1)visitor(foo ViewObjectFooSignation)error{
	// foo()
	return v.iVisitor.visitor(func(s *square)error{
		fmt.Println("ready print square version1")
		return foo(s)
	})
}

type Visitor2 struct{
	iVisitor IVisitor
}
// 函数的参数也是函数;也就是一直传递的是函数,那么一套一套,最终肯定是要执行(可以在任意层执行,当然这里是最后一环执行。)
func (v *Visitor2)visitor(foo ViewObjectFooSignation)error{
	// foo()
	return v.iVisitor.visitor(func(s *square)error{
		fmt.Println("ready print square version2", "---", s.side)
		return foo(s)
	})
}

// -------------------------------------------------------------------------

/*
func (s *square) visitor(foo ViewObjectFooSignation)error{
	return foo(s)
}
func (s *circle) visitor(foo ViewObjectFooSignation)error{
	return foo(s)
}
func (s *rectangle) visitor(foo ViewObjectFooSignation)error{
	return foo(s)
}
*/

func main() {
	s := &square{side: 2}

	var v IVisitor
	v = &Visitor1{s}
	v = &Visitor2{v}
	v.visitor(func(s *square)error{
		s.side = 10000
		return nil
	})
}

decorate visitor

 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
65
66
67
68
69
70
71
72
73
74
75
76

package main

import "fmt"

type VisitorFunc func(*Info, error) error

type Visitor interface {
	Visit(VisitorFunc) error
}

type Info struct {
	Namespace string
	Name string
	OtherThings string
}

func (info *Info) Visit(fn VisitorFunc) error {
	return fn(info, nil)
}

// ---

type DecoratedVisitor struct {
	visitor Visitor
	decorators []VisitorFunc
}

func NewDecoratedVisitor(v Visitor, fn ...VisitorFunc) Visitor {
	if len(fn) == 0 {
		return v
	}
	return DecoratedVisitor{v, fn}
}

// Visit implements Visitor
func (v DecoratedVisitor) Visit(fn VisitorFunc) error {
	return v.visitor.Visit(func(info *Info, err error) error {
		if err != nil {
			return err
		}
		if err := fn(info, nil); err !=nil {
			return err
		}
		for i := range v.decorators {
			if err := v.decorators[i](info, nil); err != nil {
				return err
			} }
		return nil
	})
}

func NameVisitor(info *Info, err error ) error {
	fmt.Printf("Name=%s, Namespace=%s\n",
		info.Name, info.Namespace)
	return nil
}

func OtherVisitor(info *Info, err error ) error {
	fmt.Printf("Other=%s\n", info.OtherThings)
	return nil
}

func LoadFile(info *Info, err error) error {
	info.Name = "Hao Chen"
	info.Namespace = "MegaEase"
	info.OtherThings = "We are running as remote team."
	return nil
}

func main() {
	info := Info{}
	var v Visitor = &info
	v = NewDecoratedVisitor(v, NameVisitor, OtherVisitor)
	v.Visit(LoadFile)
}