具有多个参数的访问者模式

Eri*_*pir 2 c++ oop design-patterns

是否可以实现访问者模式,以便:

  1. 可以在接受者上使用多个访问者。

  2. 添加新访问者时,接受者不得更改。

  3. 访问者可能必须接收参数,并且访问者之间的参数数量和类型不同。

一个示例是可以对形状执行的形状层次结构类和操作。如果操作不需要接收任何参数,那么每个操作都可以是一个访问者并继承自 Visitor 类,并且每个形状都将实现 accept 方法:

void SomeShape::accept(Visitor* visitor)
{
    visitor->visit(*this);
}
Run Code Online (Sandbox Code Playgroud)

但是,如果每个访问者都需要接收额外的参数,有没有办法使用访问者模式?有什么好的选择吗?

Que*_*tin 7

您需要将附加参数存储在访问者本身中。它们通常在构造函数中传递。这就是所谓的具体化(“实现”):本来是带参数的函数调用现在是一个对象,表示函数调用并存储参数。你现在可以不看内部地传递这个对象,这就是我们想要的。

您的accept函数应该采用 aVisitor const&以便您可以将临时文件传递给它,这很方便:

pShape->accept(SnapToPoint(x, y));
Run Code Online (Sandbox Code Playgroud)

SnapToPoint课程将看起来像:

struct SnapToPoint : Visitor {
    SnapToPoint(float x, float y) : _point(x, y) {}

    void visit(Circle   &c) const override { /* Use _point on c */ }
    void visit(Triangle &t) const override { /* Use _point on t */ }
    void visit(Square   &s) const override { /* Use _point on s */ }

private:
    Point _point;
};
Run Code Online (Sandbox Code Playgroud)

编辑:为了响应下面的依赖注入需求,一个访客工厂的例子:

struct ShapeOperationFactory {
    virtual std::unique_ptr<Visitor> snapToPoint(float x, float y) const = 0;
};

struct MyShapeOpFactory : ShapeOperationFactory {
    std::unique_ptr<Visitor> snapToPoint(float x, float y) const override {
        return std::unique_ptr<Visitor>(new SnapToPoint(x, y));
    }
};
Run Code Online (Sandbox Code Playgroud)

这将被称为:

ShapeOperationFactory *pFactory = /* Get a factory */;
pShape->accept(pFactory->snapToPoint(4.0f, 7.0f));
Run Code Online (Sandbox Code Playgroud)

看到它在这里工作。请注意,此时我必须采取Visitor实例std::unique_ptr,因为工厂是通用的。

编辑 2:刷新了我对临时生命周期的记忆。我已将accept函数回滚到 a Visitor const&,请在此处查看结果。