在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接口,这是愚蠢的重复和大量的文件......
你有什么想法如何更好地做到这一点?
非常感谢!
有没有办法实现访客设计模式没有循环依赖?我的意思是访客需要一个访问对象.并且访问对象需要访问者接受.最终两者都相互依赖.
我认为编写通用访问者基类模板将是一个简单的练习。目标是能够写
\n\ntypedef visitor<some_base, some_derived1, some_derived2> my_visitor;\nRun Code Online (Sandbox Code Playgroud)\n\n...然后让 my_visitor 成为功能上等效于的类型
\n\nstruct my_visitor {\n virtual void visit(some_base&) {}\n virtual void visit(some_derived1&) {}\n virtual void visit(some_derived2&) {}\n};\nRun 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) 这里讨论了Command和Servant模式的相似之处.但另一方面,我看到仆人与访客非常相似,而且非常相似,我不知道有什么区别?两者都通过添加功能为其他类对象服务.但命令模式不会添加功能,而是包装它,对吧?请解释一下我的困惑在哪里.
我正在使用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) 我想在我的 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”存在于树下的某个位置。我希望仅在第二次转换完成后才进行第一次转换。我该如何实现这一点?
我正在修改我前段时间使用的访客模式。我们有基类 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()的好处吗?
我很难理解变体。
我读到,我可以使用 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 提供调用运算符重载也不起作用。
如果我尝试为调用运算符包含通用引用重载,它只会匹配所有内容并且不再使用两个特定重载
以下代码示例演示了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关键字,我们只能在一个文件中实现所有类型。该关键字似乎对于允许相互类型引用是必需的。
有没有一种方式可以实现这种模式,使我们不限于一个文件? …
我正在尝试一起实现一个通用的规范模式和一个通用的访问者模式。这是我的基本接口。
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
visitor-pattern ×10
c++ ×3
generics ×2
.net ×1
babeljs ×1
c# ×1
c++11 ×1
f# ×1
inheritance ×1
java ×1
javascript ×1
oop ×1
templates ×1
type-erasure ×1
types ×1
typescript ×1
variant ×1