Behavior type: X Visitor mode

Time:2022-5-6

What is the visitor pattern

Visitor is a behavioral design pattern that allows you to add new behaviors to the existing class hierarchy without modifying the existing code.

Why use visitor mode

Visitor pattern suggests putting new behavior into a separate class called visitor rather than trying to integrate it into existing classes. Now the original object that needs to perform the operation will be passed to the method in the visitor as a parameter, so that the method can access all the necessary data contained in the object. When there is no meaning in the hierarchy of some classes, it can be used only when there is no meaning in other classes.

How to implement visitor mode

Here, three examples of structures describing shapes are used (circle, square, rectangle). The method of calculating their center point and area adopts the way of visitors. The accept method here changes the original encapsulation. However, there will only be one such change. If multiple behaviors are added, only one can accept.

shape.go

package visitor

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

circle.go

package visitor

type circle struct {
	radius int
}

func (c *circle) accept(v visitor) {
	v.visitForCircle(c)
}

func (c *circle) getType() string {
	return "Circle"
}

square.go

package visitor

type square struct {
	side int
}

func (s *square) accept(v visitor) {
	v.visitForSquare(s)
}

func (s *square) getType() string {
	return "Square"
}

rectangle.go

package visitor

type rectangle struct {
	l int
	b int
}

func (t *rectangle) accept(v visitor) {
	v.visitForRectangle(t)
}

func (t *rectangle) getType() string {
	return "rectangle"
}

visitor.go

package visitor


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

area_calculator.go

package visitor

import (
	"fmt"
	"math"
)

type areaCalculator struct {
	area int
}

func (a *areaCalculator) visitForSquare(s *square) {
	a.area = s.side * s.side
	fmt. Println ("calculate square area")
}

func (a *areaCalculator) visitForCircle(s *circle) {
	a.area = int(math.Pi * float64(s.radius * s.radius))
	fmt. Println ("calculate area of circle")
}
func (a *areaCalculator) visitForRectangle(s *rectangle) {
	a.area = s.l * s.b
	fmt. Println ("calculate area of Rectangle")
}

middle_coordinates.go

package visitor

import "fmt"

type middleCoordinates struct {
	x int
	y int
}

func (a *middleCoordinates) visitForSquare(s *square) {
	a.x = s.side / 2
	a.y = s.side / 2
	fmt. Println ("calculate the center coordinate of the square")
}

func (a *middleCoordinates) visitForCircle(c *circle) {
	a.x = c.radius
	a.y = c.radius
	fmt. Println ("calculate the center coordinate of the circle")
}
func (a *middleCoordinates) visitForRectangle(t *rectangle) {
	a.x = t.b / 2
	a.y = t.l / 2
	fmt. Println ("calculate the center coordinates of the rectangle")
}

example. Go client call example

package visitor

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

	areaCalculator := &areaCalculator{}

	square.accept(areaCalculator)
	circle.accept(areaCalculator)
	rectangle.accept(areaCalculator)

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

//Operation results:
//Calculate the area of a square
//Calculate the area of a circle
//Calculate the area of the rectangle
//Calculate the center coordinates of the square
//Calculate the center coordinates of the circle
//Calculate the center coordinates of the rectangle

advantage

  1. Opening and closing principle. You can introduce new behaviors that execute on different kinds of objects without modifying these classes.
  2. Single responsibility principle. Different versions of the same behavior can be moved to the same class.

shortcoming

  1. Adding new element classes is difficult. In the visitor mode, every time a new element class is added, the corresponding specific operation must be added to each specific visitor class, which violates the “opening and closing principle”.
  2. Destroy the package. In the visitor pattern, specific elements publish details to visitors, which destroys the encapsulation of objects.
  3. It violates the principle of inversion of dependence. The visitor pattern relies on concrete classes rather than abstract classes.

Recommended Today

Big data Hadoop — spark SQL + spark streaming

catalogue 1、 Spark SQL overview 2、 Sparksql version 1) Evolution of sparksql 2) Comparison between shark and sparksql 3)SparkSession 3、 RDD, dataframes and dataset 1) Relationship between the three 1)RDD 1. Core concept 2. RDD simple operation 3、RDD API 1)Transformation 2)Action 4. Actual operation 2)DataFrames 1. DSL style syntax operation 1) Dataframe creation 2. SQL […]