1
0
mirror of https://github.com/tmrts/go-patterns.git synced 2024-12-01 17:26:03 +03:00

behavioral/visitor: implement visitor pattern

This commit is contained in:
Serge Bishyr 2017-10-18 16:31:29 +03:00
parent f978e42036
commit 8cbceb99c5
2 changed files with 144 additions and 0 deletions

80
behavioral/visitor.md Normal file
View File

@ -0,0 +1,80 @@
# Visitor Pattern
Visitor behavioral design pattern provides a way to separate an algorithm from an object on which it operates.
It gives the ability to extend the existing object without modifying the object itself.
## Implementation
```go
type Visitor interface {
visitCircle(circle Circle) string
visitLine(line Line) string
}
type Shape interface {
accept(Visitor) string
}
type Circle struct {
Rad int
}
func (c Circle) accept(v Visitor) string {
return v.visitCircle(c)
}
type Line struct {
Len int
}
func (l Line) accept(v Visitor) string {
return v.visitLine(l)
}
```
## Usage
### JSON marshaller
```go
type JsonVisitor struct {
}
func (*JsonVisitor) visitCircle(circle Circle) string {
return fmt.Sprintf(`{"type": "circle", "radius": "%v"}`, circle.Rad)
}
func (*JsonVisitor) visitLine(line Line) string {
return fmt.Sprintf(`{"type": "line", "length": "%v"}`, line.Len)
}
```
```go
circle := Circle{12}
line := Line{42}
jsonVisitor := JsonVisitor{}
fmt.Println(circle.accept(&jsonVisitor))
fmt.Println(line.accept(&jsonVisitor))
```
### XML marshaller
```go
type XmlVisitor struct {
}
func (*XmlVisitor) visitCircle(circle Circle) string {
return fmt.Sprintf(`<circle><radius>%d</radius></circle>`, circle.Rad)
}
func (*XmlVisitor) visitLine(line Line) string {
return fmt.Sprintf(`<line><length>%d</length></line>`, line.Len)
}
```
```go
circle := Circle{12}
line := Line{42}
xmlVisitor := XmlVisitor{}
fmt.Println(circle.accept(&xmlVisitor))
fmt.Println(line.accept(&xmlVisitor))
```

View File

@ -0,0 +1,64 @@
package main
import (
"fmt"
)
type Visitor interface {
visitCircle(circle Circle) string
visitLine(line Line) string
}
type Shape interface {
accept(Visitor) string
}
type Circle struct {
Rad int
}
func (c Circle) accept(v Visitor) string {
return v.visitCircle(c)
}
type Line struct {
Len int
}
func (l Line) accept(v Visitor) string {
return v.visitLine(l)
}
type JsonVisitor struct {
}
func (*JsonVisitor) visitCircle(circle Circle) string {
return fmt.Sprintf(`{"type": "circle", "radius": "%v"}`, circle.Rad)
}
func (*JsonVisitor) visitLine(line Line) string {
return fmt.Sprintf(`{"type": "line", "length": "%v"}`, line.Len)
}
type XmlVisitor struct {
}
func (*XmlVisitor) visitCircle(circle Circle) string {
return fmt.Sprintf(`<circle><radius>%d</radius></circle>`, circle.Rad)
}
func (*XmlVisitor) visitLine(line Line) string {
return fmt.Sprintf(`<line><length>%d</length></line>`, line.Len)
}
func main() {
circle := Circle{12}
line := Line{42}
jsonVisitor := JsonVisitor{}
fmt.Println(circle.accept(&jsonVisitor))
fmt.Println(line.accept(&jsonVisitor))
xmlVisitor := XmlVisitor{}
fmt.Println(circle.accept(&xmlVisitor))
fmt.Println(line.accept(&xmlVisitor))
}