标签: visitor-pattern

如何克服访问者实施的类型擦除问题

在C#和C++中的一些项目之后,我开始使用Java.

我想设计这样的访问者界面:

public interface ActionVisitor<A> {
    void visitAction(A action);    
}

public interface MySmallActionVisitor 
extends ActionVisitor<ActionA>,
    ActionVisitor<ActionB>
{

}

public interface MyFullActionVisitor 
extends ActionVisitor<ActionA>,
    ActionVisitor<ActionB>,ActionVisitor<ActionC>,ActionVisitor<ActionD> //....
{

}
Run Code Online (Sandbox Code Playgroud)

当然,由于类型擦除,这不起作用.(我之所以想要这样的东西,是因为我可以访问不同的Actions组,我会有不同的Visitor接口.)

我想到的唯一解决方案是声明接口

public interface ActionAVisitor {
        void visitAction(ActionA action);    
    }
public interface ActionBVisitor {
        void visitAction(ActionB action);    
    }
//...
Run Code Online (Sandbox Code Playgroud)

然后

public interface MySmallActionVisitor 
extends ActionAVisitor, ActionBVisitor
{

}
Run Code Online (Sandbox Code Playgroud)

这可行,但我不想声明所有的ActionXVisitor接口,这是愚蠢的重复和大量的文件......

你有什么想法如何更好地做到这一点?

非常感谢!

java generics visitor-pattern type-erasure

5
推荐指数
1
解决办法
617
查看次数

访客设计模式中的循环依赖

有没有办法实现访客设计模式没有循环依赖?我的意思是访客需要一个访问对象.并且访问对象需要访问者接受.最终两者都相互依赖.

oop design-patterns visitor-pattern

5
推荐指数
1
解决办法
889
查看次数

C++ 中的通用访问者基类模板 - 重载问题

我认为编写通用访问者基类模板将是一个简单的练习。目标是能够写

\n\n
typedef visitor<some_base, some_derived1, some_derived2> my_visitor;\n
Run Code Online (Sandbox Code Playgroud)\n\n

...然后让 my_visitor 成为功能上等效于的类型

\n\n
struct my_visitor {\n    virtual void visit(some_base&) {}\n    virtual void visit(some_derived1&) {}\n    virtual void visit(some_derived2&) {}\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

我可以用该类型层次结构的实际有用的派生访问者类继承它,根据需要重写不同的访问()版本。我希望它适用于具有任何继承关系的任意数量的类型,并且我不想使用任何使用 type_info 比较重新实现虚拟函数的技巧。这就是我想出的:

\n\n
#include <cstdlib>\n#include <iostream>\n#include <vector>\n\n\n/** This is the generic part that would go in a visitor.hpp header. */\ntemplate <typename T> struct visitor_base {\n    virtual void visit(T&) {};\n};\n\ntemplate <typename... T> struct visitor : visitor_base<T>... {};\n\n\n/** This is the part that is specific to a certain type hierarchy. */\nstruct base;\nstruct derived1;\nstruct …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance templates visitor-pattern c++11

4
推荐指数
1
解决办法
1548
查看次数

访客vs仆人vs命令模式

这里讨论了Command和Servant模式的相似之处.但另一方面,我看到仆人与访客非常相似,而且非常相似,我不知道有什么区别?两者都通过添加功能为其他类对象服务.但命令模式不会添加功能,而是包装它,对吧?请解释一下我的困惑在哪里.

design-patterns visitor-pattern command-pattern

4
推荐指数
1
解决办法
1879
查看次数

使用ExpressionVisitor停止遍历

我正在使用ExpressionVisitor解析表达式树来查明它是否包含指定的参数.一旦找到参数,继续遍历是没有意义的.

是否有任何方法可以通过访问者模式停止遍历,更具体地说是ExpressionVisitor在.NET中?

这是我到目前为止所做的,它正如预期的那样工作.但是一旦布尔标志设置为true,就此算法而言,停止遍历是有意义的.

public class ExpressionContainsParameterVisitor : ExpressionVisitor
{
  private bool expressionContainsParameter_;
  private ParameterExpression parameter_;

  public bool Parse(Expression expression, ParameterExpression parameterExpression)
  {
    parameter_ = parameterExpression;
    expressionContainsParameter_ = false;

    Visit(expression);

    return expressionContainsParameter_;
  }

  protected override Expression VisitParameter(ParameterExpression node)
  {
    if (node == parameter_)
    {
      expressionContainsParameter_ = true;
    }

    return node;
  }
}
Run Code Online (Sandbox Code Playgroud)

.net c# expression-trees visitor-pattern expressionvisitor

4
推荐指数
1
解决办法
240
查看次数

Babel 插件(访客模式)——它是如何工作的

我想在我的 babel 插件中做两个替换。第二次更换只能在第一次更换完成后进行。

module.exports = function(babel) {
    const t = babel.types;
    return {
        visitor: {
            FunctionExpression: function(path) {
                //Conversion to arrow functions
                path.replaceWith(t.arrowFunctionExpression(path.node.params, path.node.body, false));
            },
            ThisExpression: function(path) {
                //Converting all this expressions to identifiers so that it won't get translated differently
                path.replaceWith(t.identifier("this"));
            }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

在我的“FunctionExpression”的 AST 树中,“ThisExpression”存在于树下的某个位置。我希望仅在第二次转换完成后才进行第一次转换。我该如何实现这一点?

javascript visitor-pattern babeljs

4
推荐指数
1
解决办法
4839
查看次数

为什么在访客模式中需要accept(),为什么不能直接调用visitor.visit()?

我正在修改我前段时间使用的访客模式。我们有基类 Element,它具有虚方法accept(Visitor),并且该方法在继承自 Element 的所有类中被重写。在任何派生类中accept()所做的就是调用visitor->visit(*this)。现在,当客户端运行代码时,他/她会执行以下操作:

Visitor& theVisitor = *new ConcreteVisitor();    
for_each(elements.begin(), elements.end(), [](Element& e) { e.accept(theVisitor));})
Run Code Online (Sandbox Code Playgroud)

为什么客户端不能像这样调用visitor->visit(element):

Visitor& theVisitor = *new ConcreteVisitor();    
for_each(elements.begin(), elements.end(), [&theVisitor](Element& e) { theVisitor.visit(e); });
Run Code Online (Sandbox Code Playgroud)

调用 element.accept(visitor) 进而调用 guest.visit(element) 时有哪些有用的信息?这使得访问者模式的使用变得很麻烦,并且需要在 Element 类的所有层次结构中添加额外的代码。

那么有人可以在这里解释一下accept()的好处吗?

c++ design-patterns double-dispatch visitor-pattern

4
推荐指数
1
解决办法
1677
查看次数

访问单态的变体

我很难理解变体。

我读到,我可以使用 std::monostate 来暗示空状态作为变体中的替代方案之一。但是,如何使用 std::visit 促进的访问者模式?

#include <variant>


struct Visitor{
  void operator()(double){};
  void operator()(int){};
};

int main() {
  std::variant<std::monostate, int, double> v = 1;

  std::visit(Visitor{}, v);
}
Run Code Online (Sandbox Code Playgroud)

不起作用,为 std::monostate 提供调用运算符重载也不起作用。

如果我尝试为调用运算符包含通用引用重载,它只会匹配所有内容并且不再使用两个特定重载

c++ variant visitor-pattern

4
推荐指数
1
解决办法
7838
查看次数

如何在不限于一个文件的情况下在F#中实现访客模式?

以下代码示例演示了F#中访客模式的实现

module VisitorPattern

    type IVisitor =
        abstract Visit : ObjectA -> unit
        abstract Visit : ObjectB -> unit

    and IVisitable =
        abstract InvokeVisit : IVisitor -> unit

    and ObjectA =
        interface IVisitable with
            member this.InvokeVisit (visitor: IVisitor) =
                visitor.Visit(this)

    and ObjectB =
        interface IVisitable with
            member this.InvokeVisit (visitor: IVisitor) =
                visitor.Visit(this)

    type MyVisitor =
        member this.Visit (a : ObjectA) =
            printfn "Visited object A"

        member this.Visit (b : ObjectB) =
            printfn "Visited object B"
Run Code Online (Sandbox Code Playgroud)

这样可以很好地编译,但是IVisitable由于使用了and关键字,我们只能在一个文件中实现所有类型。该关键字似乎对于允许相互类型引用是必需的。

有没有一种方式可以实现这种模式,使我们不限于一个文件? …

f# visitor-pattern

4
推荐指数
1
解决办法
132
查看次数

尝试实现通用规范和访问者模式时,类型不满足约束并错误地扩展了接口

我正在尝试一起实现一个通用的规范模式和一个通用的访问者模式。这是我的基本接口。

export interface Specification<T, TVisitor extends SpecificationVisitor<TVisitor, T>> {
  accept(visitor: TVisitor): void;
  isSatisfiedBy(candidate: T): boolean;
  and(other: Specification<T, TVisitor>): Specification<T, TVisitor>;
  andNot(other: Specification<T, TVisitor>): Specification<T, TVisitor>;
  or(other: Specification<T, TVisitor>): Specification<T, TVisitor>;
  orNot(other: Specification<T, TVisitor>): Specification<T, TVisitor>;
  not(): Specification<T, TVisitor>;
}

export interface SpecificationVisitor<TVisitor extends SpecificationVisitor<TVisitor, T>, T> {
  visit(specification: AndSpecification<T, TVisitor>): void;
  visit(specification: AndNotSpecification<T, TVisitor>): void;
  visit(specification: OrSpecification<T, TVisitor>): void;
  visit(specification: OrNotSpecification<T, TVisitor>): void;
  visit(specification: NotSpecification<T, TVisitor>): void;
}
Run Code Online (Sandbox Code Playgroud)

为方便起见,我为基本布尔运算符实现了一些基类和一个抽象类。

export abstract class CompositeSpecification<T, TVisitor extends SpecificationVisitor<TVisitor, T>> implements Specification<T, TVisitor> …
Run Code Online (Sandbox Code Playgroud)

generics types visitor-pattern specification-pattern typescript

4
推荐指数
1
解决办法
36
查看次数