访问者

访问者

访问者是一种行为设计模式,它能将算法与其所作用的对象隔离开来。

案例:XML 文件导出

// 元素接口声明了一个`accept`(接收)方法,它会将访问者基础接口作为一个参数。
interface Shape is
    method move(x, y)
    method draw()
    method accept(v: Visitor)

// 每个具体元素类都必须以特定方式实现`accept`方法,使其能调用相应元素类的访问者方法。
class Dot extends Shape is
    // ...

    // 注意我们正在调用的`visitDot`(访问点)方法与当前类的名称相匹配。
    // 这样我们能让访问者知晓与其交互的元素类。
    method accept(v: Visitor) is
        v.visitDot(this)

class Circle extends Dot is
    // ...
    method accept(v: Visitor) is
        v.visitCircle(this)

class Rectangle extends Shape is
    // ...
    method accept(v: Visitor) is
        v.visitRectangle(this)

class CompoundShape implements Shape is
    // ...
    method accept(v: Visitor) is
        v.visitCompoundShape(this)


// 访问者接口声明了一组与元素类对应的访问方法。访问方法的签名能让访问者准
// 确辨别出与其交互的元素所属的类。
interface Visitor is
    method visitDot(d: Dot)
    method visitCircle(c: Circle)
    method visitRectangle(r: Rectangle)
    method visitCompoundShape(cs: CompoundShape)

// 具体访问者实现了同一算法的多个版本,而且该算法能与所有具体类进行交互。
//
// 访问者模式在复杂对象结构(例如组合树)上使用时能发挥最大作用。在这种情
// 况下,它可以存储算法的一些中间状态,并同时在结构中的不同对象上执行访问
// 者方法。这可能会非常有帮助。
class XMLExportVisitor implements Visitor is
    method visitDot(d: Dot) is
        // 导出点(dot)的 ID 和中心坐标。

    method visitCircle(c: Circle) is
        // 导出圆(circle)的 ID、中心坐标和半径。

    method visitRectangle(r: Rectangle) is
        // 导出长方形(rectangle)的 ID、左上角坐标、宽和长。

    method visitCompoundShape(cs: CompoundShape) is
        // 导出图形(shape)的 ID 和其子项目的 ID 列表。


// 客户端代码可在不知晓具体类的情况下在一组元素上运行访问者操作。“接收”操
// 作会将调用定位到访问者对象的相应操作上。
class Application is
    field allShapes: array of Shapes

    method export() is
        exportVisitor = new XMLExportVisitor()

        foreach (shape in allShapes) do
            shape.accept(exportVisitor)