标签: visitor-pattern

访客模式的变化:为什么不将第二次调度移动到访问者的"访问"方法中?

介绍

显然,我在整个程序员生活中一直在做一个"非正统的"访客模式.

是的,我从Visitor的Visit方法发送到具体的复合元素访问方法.

我认为这就是我学习它的方法,但是现在我找不到它的任何例子,我从中学到的来源已经消失了.

现在,面对压倒性的证据表明具体的元素调度进入复合元素的Accept方法,我想知道我这样做的方式至少有一些优势.在我看来,两个优点是:

  1. 我有一个地方可以决定如何派遣:基地访客.
  2. 我可以添加新的复合元素类型,并让基本访问者忽略它们,但派生的访问者可以覆盖Visit它们来处理它们.

例子

这是基本的Composite/Visitor模型:

// "Unorthodox" version
public class BaseVisitor 
{
    public virtual void Visit(CompositeElement e)
    {
         if(e is Foo)
         {
             VisitFoo((Foo)e);
         }
         else if(e is Bar)
         {             
             VisitBar((Bar)e);
         }
         else
         {
             VisitUnknown(e);
         }
    }

    protected virtual void VisitFoo(Foo foo) { }
    protected virtual void VisitBar(Bar bar) { }
    protected virtual void VisitUnknown(CompositeElement e) { }
} 

public class CompositeElement 
{
    public virtual void Accept(BaseVisitor visitor) { } 
} …
Run Code Online (Sandbox Code Playgroud)

design-patterns visitor-pattern

3
推荐指数
2
解决办法
3506
查看次数

如何确定Eclipse JDT中方法或字段的修饰符?

我正在为Eclipse JDT编写一些简单的AST访问者.我有一个MethodVisitorFieldVisitor每个扩展的类ASTVisitor.举个MethodVisitor例子.在该类的Visit方法(这是一个覆盖),我能够找到每个MethodDeclaration节点.当我有其中一个节点时,我想查看它Modifiers是否是它(public或者private也许是其他修饰符).有一个方法叫做getModifiers(),但我不清楚如何使用它来确定应用于特定的修饰符的类型MethodDeclaration.我的代码发布在下面,如果您有任何想法如何继续,请告诉我.

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.MethodDeclaration;

public class MethodVisitor extends ASTVisitor {

    private List<MethodDeclaration> methods;

    // Constructor(s)
    public MethodVisitor() {
        this.methods = new ArrayList<MethodDeclaration>();
    }

    /**
     * visit - this overrides the ASTVisitor's visit and allows this
     * class to visit MethodDeclaration nodes in the AST.
     */
    @Override
    public boolean visit(MethodDeclaration node) {
        this.methods.add(node); …
Run Code Online (Sandbox Code Playgroud)

java modifier abstract-syntax-tree visitor-pattern eclipse-jdt

3
推荐指数
1
解决办法
2306
查看次数

Antlr4 Python3 目标访问者不可用?

我尝试遵循Antlr4 参考书和 Python3 目标,但我陷入了计算器示例。在Antlr4 文档上它说

AntLR 的 Python 实现尽可能接近 Java 实现,因此您应该不会觉得将示例改编为 Python 很困难

但我还没明白。

java代码访问者有一个.visit方法,而在python中我没有这个方法。我认为这是因为在java中访问方法具有令牌的参数重载。在python中我们有visitProg(),等visitAssign()visitId()但是现在我不能写,value = self.visit(ctx.expr())因为我们不知道要调用什么访问?

或者我在某处遗漏了指令?

visitor-pattern antlr4 python-3.4

3
推荐指数
1
解决办法
2996
查看次数

访问者模式 VS 迭代器模式:跨层次结构类访问?

我正在研究访问者模式的优点,并引用设计模式

但是迭代器不能跨具有不同类型元素的对象结构工作。例如,第 295 页定义的 Iterator 接口只能访问 Item 类型的对象:

template <class Item> 
clas  Iterator { // ... Item CurrentItem() const; };
Run Code Online (Sandbox Code Playgroud)

这意味着迭代器可以访问的所有元素都有一个共同的父类 Item。访客没有此限制...

class Visitor {
public:
// ...
void VisitMyType(MyType*);
void VisitYourType(YourType*);
};
Run Code Online (Sandbox Code Playgroud)

MyType 和 YourType 根本不必通过继承关联。

我同意这句话,但我无法找出访问者模式可以探索List其中收集的对象与超类不相关的结构(如 a )的示例。

换句话说,您能给我举一个例子来证明上述特征是正确的吗?

iterator visitor-pattern

3
推荐指数
2
解决办法
7894
查看次数

根据类中的字段选择方法

所以我有一个包含字符串字段的类:

public class A {
    private String type = ...
    public String getType(){
        return this.type;
    }
    public void setType(String type){
        this.type = type;
    }
}
Run Code Online (Sandbox Code Playgroud)

我还列出了所有可能的类型,将来有十二种甚至更多.

现在我想编写一个获取类A对象的方法,并根据类中的"类型"调用特定方法.有没有比编写12个(或更多)if语句更聪明的解决方案?
通常我会使用访问者模式,但我不想创建十二个新类.

编辑:
我最终创建了一个

Map<String,Function<A,String>> map = new HashMap<String,Function<A,String>>
Run Code Online (Sandbox Code Playgroud)

然后打电话

A a;
...
map.get(a.getType).apply(a);
Run Code Online (Sandbox Code Playgroud)

java field visitor-pattern

3
推荐指数
1
解决办法
991
查看次数

访客模式,为什么有用?

我使用了这里给出的访客示例,我们有这个:

.------------------------.
|        Flower          |
+------------------------+ 
| +accept(visitor)       |
| +pollinate(pollinator) |
| +eat(eater)            |
'------------------------'
Run Code Online (Sandbox Code Playgroud)

我们还有可以是 a 的aBug和a ,以及可以是一朵花的 a 。BeepollinateFlowerPredatoreat

使用访问者模式我可以这样写:

bee = Bee()
fly = Fly()
worm = Worm()

# Using the visitor pattern:
for flower in flowerGen(10):    
    for object in [bee, fly, worm]:
        flower.accept(object)
Run Code Online (Sandbox Code Playgroud)

但代码在没有访问者的情况下仍然具有可读性和功能性:

# Without visitor pattern 
for flower in flowerGen(10):
    for object in [bee, fly, worm]:
        object.visit(flower)
Run Code Online (Sandbox Code Playgroud)

问题是,此示例中的访问者模式有哪些优点?

python design-patterns visitor-pattern

3
推荐指数
1
解决办法
1681
查看次数

一种查找Java对象初始化而不是声明类型的方法?

我不知道我在这里是否遗漏了什么,但我无法将对象转换为其实际的初始化类型.基本上,如果我用"SuperClass sc = new SubClass()"创建一个对象,那么我在sc上调用一个方法,我希望该方法能够调用方法(Subclass)而不是方法(Superclass).示例如下:

public class Example
{
    public static void act(SuperClass a) {
        System.out.println("SuperClass");
    }

    public static void act(SubClass a) {
        System.out.println("SubClass");
    }

    public static void main(String[] args) {
        SuperClass sc = new SubClass();

        // want to find a way to call act(SubClass) instead of act(SuperClass)
        act(sc);
   }
}

class SuperClass {}
class SubClass extends SuperClass {}
Run Code Online (Sandbox Code Playgroud)

我现在正在使用访问者模式,但我想知道是否有其他方法可以通过Java Reflection API进行此操作?

非常感谢提前!

==编辑==

我知道通常使用OO最好将功能强加回超类/子类本身,但对于我的特定用例,我有一堆子类是不可变的模型类,应该传递给不同类型的执行引擎(想想不同的"示例"类).子类/模型类应该只保存不可变信息,而实际的实际功能在于执行引擎(Example类).这就是为什么我想知道访客模式的替代方案.有没有人有办法在Java中恢复实际的"初始化"信息?如果是这样,非常感谢你.

而且由于问题的本质,我不能使用直接投射......想象一下,如果我有一个SuperClass的arraylist,其中每个元素可能是SubClass1,SubClass2,SubClass3,都是从SuperClass扩展的.

现在,当你从Arraylist中取出东西时,你得到一个SuperClass对象,即使它们可能真的是SubClass1,SubClass2,SubClass3等.

接下来,我想调用act(SubClass1),并能够在当前类型上调用正确的act()方法.所以我想最终调用act(SubClass1),act(SubClass2),act(SubClass3),而不是act(SuperClass).

==再次编辑==

我通过Java Reflection API想出了一种方法,通过使用Class.forName(classname)查找SubClass的实际底层类型,然后使用正确的方法签名动态调用该方法.对于那些对此问题感兴趣的人,我已经在本页的某个地方以答案的形式写了这篇文章.请注意,这不是一种非常有效的方式来完成我在这里尝试做的事情,如果你遇到我的情况,你最好使用访问者模式或if-else语句.


所以Nicola Musatti给出的答案最接近于回答我的问题,尽管正如他已经指出的那样,随着SubClasses数量的增长,if-else语句列表变得非常长.我将选择他的答案作为接受答案,因为我在我的问题中没有明确说明我希望避免if-else检查.

无论如何,所以我今天使用Java Reflection API玩了一下并想出了这个:

SuperClass sc = …
Run Code Online (Sandbox Code Playgroud)

java visitor-pattern

2
推荐指数
1
解决办法
317
查看次数

将访客模式与模板派生类一起使用

我尝试使用模板化派生类实现访问者模式

我使用gcc 4.5

这里是VisitorTemplate.hpp,我专门在类Visitor中派生,但我希望能够处理任何类型:

编辑:感谢interjay的建议,代码现在编译并运行没有错误

#ifndef VISITORTEMPLATE_HPP_
#define VISITORTEMPLATE_HPP_

#include <iostream>
#include <string>
using namespace std;

template<class T> Derived;

class Visitor
{
  public:
    virtual void visit(Derived<string> *e) = 0;
};

class Base
{
  public:
    virtual void accept(class Visitor *v) = 0;
};

template<class T>
Derived: public Base
{
  public:
    virtual void accept(Visitor *v)
    {
       v->visit(this);
    }
    string display(T arg)
    {
       string s = "This is : " + to_string(arg);
       return s;
    }
};

class UpVisitor: public Visitor
{
   virtual void …
Run Code Online (Sandbox Code Playgroud)

c++ templates design-patterns visitor-pattern c++11

2
推荐指数
1
解决办法
7230
查看次数

根据 Java 中 Object 的类型选择实现

我有一个父类型

public class IObject{}
Run Code Online (Sandbox Code Playgroud)

并且可以有很多子类(甚至是未来的新子类)

public class Object1 extends IObject{}
public class Object2 extends IObject{}
public class Object3 extends IObject{}
...
public class ObjectN extends IObject{}
Run Code Online (Sandbox Code Playgroud)

然后根据这些对象的类型我必须做不同的操作。

public class StrategyForObject1(){void do{}}
public class StrategyForObject2(){void do{}}
public class StrategyForObject3(){void do{}}
...
public class StrategyForObjectN(){void do{}}
Run Code Online (Sandbox Code Playgroud)

所以我想从我的 Context 类:

   public Conext {
    IObject o;

    public void setObject(IObject o) {
        this.o = o;
    }

    void logic() {
        if (o instanceOf Object1) {
            new StrategyForObject1().do();
        }
        if (o instanceOf Object2) {
            new StrategyForObject2().do();
        } …
Run Code Online (Sandbox Code Playgroud)

java design-patterns strategy-pattern visitor-pattern genetic-algorithm

2
推荐指数
1
解决办法
2372
查看次数

QVariant的访客模式(无需手动型式测试和铸造)

Qt的QVariant类是否有任何现有(且方便)的访问者模式实现?

如果没有,是否有可能实现类似的东西boost::apply_visitor(),即最小化测试类型和铸造的重复?

我希望通过以下方式实现目标:

/* I have a QVariant that can contain anything, including user types */
QVariant variant;    

/* But in my Visitor I'm interested only in ints and QStrings (for the sake of the example) */
struct Visitor
{
   void operator()(int i) { /* do something with int */ } 
   void operator()(QString s) { /* ...or QString */ }
};

/* The question is: */
/* Can this be implemented in a generic way (without resorting to …
Run Code Online (Sandbox Code Playgroud)

c++ qt visitor visitor-pattern qvariant

2
推荐指数
1
解决办法
538
查看次数