dushaoshuai / dushaoshuai.github.io

https://www.shuai.host
0 stars 0 forks source link

Visitor #69

Open dushaoshuai opened 1 year ago

dushaoshuai commented 1 year ago

Visitor 模式可以在不改变现有类的情况下,为其添加新的行为(第二种说法:可以将算法与操作对象分离)。

一个简单的实现

visitor.go:

type Node interface {
    IsNode()
}

type DotNode struct{}

func (d *DotNode) IsNode() {}

type CircleNode struct{}

func (c *CircleNode) IsNode() {}

type RectangleNode struct{}

func (r *RectangleNode) IsNode() {}

type CompoundNode struct{}

func (c *CompoundNode) IsNode() {}

type Visitor interface {
    Visit(Node)
}

type Visitor1 struct{}

func (v *Visitor1) Visit(n Node) {
    switch n.(type) { // a Visitor doesn't have to visit all Node type
    case *DotNode:
        fmt.Println("visitor1 visiting a DotNode")
    case *CircleNode:
        fmt.Println("visitor1 visiting a CircleNode")
    case *CompoundNode:
        fmt.Println("visitor1 visiting a CompoundNode")
    }
}

type Visitor2 struct{}

func (v *Visitor2) Visit(n Node) {
    switch n.(type) { // a Visitor doesn't have to visit all Node type
    case *CircleNode:
        fmt.Println("visitor2 visiting a CircleNode")
    case *RectangleNode:
        fmt.Println("visitor2 visiting a RectangleNode")
    }
}

visitor_test.go:

func Example_visitor() {
    nodes := []visitor.Node{
        &visitor.DotNode{},
        &visitor.CircleNode{},
        &visitor.RectangleNode{},
        &visitor.CompoundNode{},
    }

    visitor1 := &visitor.Visitor1{}
    for _, n := range nodes {
        visitor1.Visit(n)
    }
    fmt.Println()
    visitor2 := &visitor.Visitor2{}
    for _, n := range nodes {
        visitor2.Visit(n)
    }

    // Output:
    // visitor1 visiting a DotNode
    // visitor1 visiting a CircleNode
    // visitor1 visiting a CompoundNode
    //
    // visitor2 visiting a CircleNode
    // visitor2 visiting a RectangleNode
}

See also