简介
访问者模式(Visitor Pattern)是一种行为型设计模式,它在不改变被访问对象的前提下,定义了新的操作。访问者模式通过在被访问的对象中加入一个对外提供的接受访问者的接口,使得访问者可以访问到对象的内部状态。
访问者模式主要有一些几个角色:
访问者(Visitor)
定义了对每个具体元素(被访问的对象)的访问操作。通常会有多个访问者,每个访问者实现不同的访问操作。
具体访问者(ConcreteVisitor)
实现了访问者接口,具体实现对每个具体元素的访问操作。
元素(Element)
定义了一个接受访问者的接口,通常包含一个 accept 方法。
具体元素(ConcreteElement)
用于接受访问者的访问。
对象结构(Object Structure)
被访问的对象的集合,可以是一个集合、列表、树等结构。
你想买车,哪些4S店不知道从哪知道你想买车,纷纷上门拜访来推销他们的车辆,比如BMW的销售、BenZ的销售等等,然后他们会说他们的车有哪些不同之处。
Demo
// Visitor 访问者接口
type Visitor interface {
Visit()
}
// BMWVisitor 具体访问者
type BMWVisitor struct {
}
func (b BMWVisitor) Visit() {
fmt.Println("我是宝马销售,我们的车是豪华品牌")
}
type MazdaVisitor struct {
}
func (b MazdaVisitor) Visit() {
fmt.Println("我是马自达销售,我们的车,现在不堵了")
}
// IElement 元素接口
type IElement interface {
Accept(visitor Visitor)
}
// Element 具体元素
type Element struct {
}
func (e *Element) Accept(v Visitor) {
v.Visit()
}
测试
func TestVisitor(t *testing.T) {
e := new(Element)
e.Accept(new(BMWVisitor)) // 我是宝马销售,我们的车是豪华品牌
e.Accept(new(MazdaVisitor)) // 我是马自达销售,我们的车,现在不堵了
}
作用和场景
访问者模式通过将算法封装在访问者中,实现了对象结构和算法的分离。被访问的对象无需关心具体的访问算法,而访问者可以轻松增加新的操作而不影响被访问对象的结构。
支持多种操作 可以定义多个具体的访问者,每个访问者实现一种具体的操作。这样,可以在不修改被访问对象的前提下,增加新的操作,从而增加系统的灵活性。
访问者可以保持状态
访问者模式允许访问者在访问对象的过程中保持状态。这对于对一组相关的对象执行操作,并保持一些中间状态的情况非常有用。
当对象结构相对稳定,但经常需要添加新的操作时,使用访问者模式可以避免修改对象结构的情况下扩展操作。
当需要在对象结构上执行不同、相互关联的操作,并且这些操作无法被合理地放在被访问对象的类中时,访问者模式是一种合适的选择。
总体而言,访问者模式适用于对象结构相对稳定,但需要在其上定义新的操作,并且这些操作有多样性、不断变化的情况。