XingPiaoLiang's

Back

访问者模式#

访问者模式通过引入 Visitor 角色,以及 Accept 方法,依靠双分派思想,来实现向已有类添加新特性但不改变原本类整体结构,实现行为和已有类的解耦。

主要思想#

访问者模式建议将新行为放入到一个名为访问者(Visitor)的独立类中,而不是试图将其整合到已有类中。现在,需要执行该新操作的原始对象将作为参数被传递给访问者中的方法,让方法能访问对象所包含的一切必要数据。同时访问者也可以根据不同的原有类,声明不同的方法签名(更加便于区分):

type ExportVisitor interface {
    doForCity(c City)
    doForIndustry(c Industry)
    doForSightSeeing(c SightSeeing)
    .....
}
go

但是不幸的是,依托双分派机制,我们还是需要略微改动已有类,因为在选择如何调用这些方法的时候,这些方法的签名各不相同,我们不能使用多态机制。所以如果需要挑选出能够理特定对象的方法,我们则需要一个一个检查该类的类型…

for _, node := range nodes {
    switch t := node.(type) {
        case City:
            doForCity(t)
        case Industry:
            doForIndustry(t)
        case SightSeeing:
            doForSightSeeing(t)
        ...
    }
}
go

Accept 方法将很好的解决了上面的问题。与其让客户端来选择调用正确版本的方法,不如直接将选择权委派给作为参数传递给访问者的对象本身,因为该对象完全明白自身的类,自然而然地他们就可以执行相应的方法。原有类接受一个访问者,并告知他应该执行的正确的访问者方法。

type Node interface {
    Accept(v Visitor)
}

func (c *City) Accept(v Visitor) {
    v.doForCity(c)
}

func (c *Industry) Accept(v Industry) {
    v.doForCity(c)
}

func (c *SightSeeing) Accept(v SightSeeing) {
    v.doForCity(c)
}
go

整体结构#

设计模式-行为型-访问者
https://astro-pure.js.org/blog/visitor
Author erasernoob
Published at June 10, 2025
Comment seems to stuck. Try to refresh?✨