0
点赞
收藏
分享

微信扫一扫

Go 设计模式中访问者模式


鱼弦:全栈领域创作新星创作者 、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen)

Go 设计模式中访问者模式_golang

在Go设计模式中,访问者模式(Visitor Pattern)是一种行为型模式,用于将算法与数据结构分离,使得算法可以独立地操作数据结构的不同元素,同时遵循开闭原则。

原理详细解释:
访问者模式的核心思想是将数据结构与对数据的操作分离。它通过定义一个访问者(Visitor)接口,该接口包含了对数据结构中每个元素的操作方法。数据结构中的每个元素都要实现一个接受访问者的方法,将自身传递给访问者,并在访问者中调用相应的操作方法。

在访问者模式中,通常有以下几个角色:

  1. Visitor(访问者接口):定义了对数据结构中每个元素的操作方法。
  2. ConcreteVisitor(具体访问者类):实现了Visitor接口,具体实现了对数据结构中每个元素的操作方法。
  3. Element(元素接口):定义了接受访问者的方法。
  4. ConcreteElement(具体元素类):实现了Element接口,实现了接受访问者的方法,并将自身传递给访问者。
  5. ObjectStructure(对象结构):包含了一个或多个元素,提供了遍历元素的方法。

访问者模式的优点在于可以在不修改数据结构的情况下,增加新的操作。但缺点是增加新的元素类型会较为困难,需要修改所有的访问者类。

底层结构图:
以下是访问者模式的底层结构图:

+-------------------------+
    |       Visitor           |
    +-------------------------+
    | + VisitConcreteElementA |
    | + VisitConcreteElementB |
    +-------------------------+
              /|\
               |
               |
    +-------------------------+
    |    ConcreteVisitorA     |
    +-------------------------+
    | + VisitConcreteElementA |
    +-------------------------+
              /|\
               |
               |
    +-------------------------+
    |    ConcreteVisitorB     |
    +-------------------------+
    | + VisitConcreteElementB |
    +-------------------------+
               /|\
                |
                |
    +-----------------------+
    |      Element          |
    +-----------------------+
    | + Accept(Visitor)     |
    +-----------------------+
              /|\
               |
               |
    +-----------------------+
    |  ConcreteElementA     |
    +-----------------------+
    | + Accept(Visitor)     |
    +-----------------------+
              /|\
               |
               |
    +-----------------------+
    |  ConcreteElementB     |
    +-----------------------+
    | + Accept(Visitor)     |
    +-----------------------+
               |
               |
    +-----------------------+
    |   ObjectStructure     |
    +-----------------------+
    | + Attach(Element)     |
    | + Detach(Element)     |
    | + Accept(Visitor)     |
    +-----------------------+

使用场景解释:
访问者模式适用于以下情况:

  1. 当一个数据结构中的元素类型很少发生变化,但需要定义多个不同的操作时,可以使用访问者模式。它将每个操作都封装在一个独立的访问者类中,使得操作可以独立地变化和扩展。
  2. 当一个数据结构中的元素类型较多,但每个元素都需要进行不同的操作时,可以使用访问者模式。通过访问者模式,可以避免在数据结构中添加大量的条件语句,使得代码更加清晰和可维护。
  3. 当对数据结构的元素进行操作时,不希望修改元素的类定义,可以使用访问者模式。访问者模式将操作封装在访问者类中,使得操作可以独立于元素类进行扩展。

代码示例实现:
下面是一个简单的访问者模式的示例,假设有以下是一个使用Golang实现的访问者模式示例:

package main

import "fmt"

// Visitor 访问者接口
type Visitor interface {
	VisitConcreteElementA(element ConcreteElementA)
	VisitConcreteElementB(element ConcreteElementB)
}

// ConcreteVisitorA 具体访问者A
type ConcreteVisitorA struct{}

// VisitConcreteElementA 具体访问者A对ConcreteElementA的操作
func (v ConcreteVisitorA) VisitConcreteElementA(element ConcreteElementA) {
	fmt.Println("ConcreteVisitorA访问ConcreteElementA")
}

// VisitConcreteElementB 具体访问者A对ConcreteElementB的操作
func (v ConcreteVisitorA) VisitConcreteElementB(element ConcreteElementB) {
	fmt.Println("ConcreteVisitorA访问ConcreteElementB")
}

// ConcreteVisitorB 具体访问者B
type ConcreteVisitorB struct{}

// VisitConcreteElementA 具体访问者B对ConcreteElementA的操作
func (v ConcreteVisitorB) VisitConcreteElementA(element ConcreteElementA) {
	fmt.Println("ConcreteVisitorB访问ConcreteElementA")
}

// VisitConcreteElementB 具体访问者B对ConcreteElementB的操作
func (v ConcreteVisitorB) VisitConcreteElementB(element ConcreteElementB) {
	fmt.Println("ConcreteVisitorB访问ConcreteElementB")
}

// Element 元素接口
type Element interface {
	Accept(visitor Visitor)
}

// ConcreteElementA 具体元素A
type ConcreteElementA struct{}

// Accept 接受访问者的操作
func (e ConcreteElementA) Accept(visitor Visitor) {
	visitor.VisitConcreteElementA(e)
}

// ConcreteElementB 具体元素B
type ConcreteElementB struct{}

// Accept 接受访问者的操作
func (e ConcreteElementB) Accept(visitor Visitor) {
	visitor.VisitConcreteElementB(e)
}

// ObjectStructure 对象结构
type ObjectStructure struct {
	elements []Element
}

// Attach 添加元素
func (o *ObjectStructure) Attach(element Element) {
	o.elements = append(o.elements, element)
}

// Detach 移除元素
func (o *ObjectStructure) Detach(element Element) {
	for i, e := range o.elements {
		if e == element {
			o.elements = append(o.elements[:i], o.elements[i+1:]...)
			break
		}
	}
}

// Accept 接受访问者的操作
func (o ObjectStructure) Accept(visitor Visitor) {
	for _, element := range o.elements {
		element.Accept(visitor)
	}
}

func main() {
	// 创建具体元素
	elementA := ConcreteElementA{}
	elementB := ConcreteElementB{}

	// 创建具体访问者
	visitorA := ConcreteVisitorA{}
	visitorB := ConcreteVisitorB{}

	// 创建对象结构
	objectStructure := ObjectStructure{}
	objectStructure.Attach(elementA)
	objectStructure.Attach(elementB)

	// 对象结构接受具体访问者A的操作
	objectStructure.Accept(visitorA)

	// 对象结构接受具体访问者B的操作
	objectStructure.Accept(visitorB)
}

在上面的示例中,我们定义了Visitor接口和两个具体的Visitor类:ConcreteVisitorA和ConcreteVisitorB。然后我们定义了Element接口和两个具体的Element类:ConcreteElementA和ConcreteElementB。最后,我们定义了ObjectStructure类来管理元素,并实现了Attach、Detach和Accept方法。在main函数中,我们创建了具体的元素和访问者,并将元素添加到对象结构中。然后,我们分别让对象结构接受具体访问者A和具体访问者B的操作。

文献材料链接:
以下是一些关于访问者模式的参考文献链接:

  1. Design Patterns: Elements of Reusable Object-Oriented Software (Gang of Four book)
  • 链接:Amazon.com
  1. SourceMaking - Visitor Pattern
  • 链接:Visitor Design Pattern
  1. Refactoring Guru - Visitor Pattern
  • 链接:Visitor

当前都有哪些产品在使用:

访问者模式是一种常用的设计模式,可以在许多不同的领域和产品中找到应用。以下是一些使用访问者模式的常见产品和框架:

  1. 编译器和解析器:访问者模式常用于编译器和解析器的实现中,用于遍历抽象语法树(Abstract Syntax Tree,AST)并执行相应的操作。
  2. 文档处理工具:访问者模式可以用于处理文档结构,例如解析和操作HTML、XML或Markdown文档。
  3. 图形处理库:访问者模式可以用于图形处理库,用于遍历图形对象的层次结构并执行相应的操作,如绘制、变换或计算。
  4. 数据库访问框架:访问者模式可以用于数据库访问框架,用于遍历数据库表或查询结果,并执行相应的操作,如映射到对象模型或执行业务逻辑。
  5. 游戏引擎:访问者模式可以用于游戏引擎中的场景管理、碰撞检测和物理引擎等方面,用于遍历游戏对象并执行相应的操作。
举报

相关推荐

0 条评论