标签: visitor-pattern

使用访客设计模式的一个很好的理由?

在你告诉我已经存在类似的问题之前,是的,我知道,我已经读过.但那里的问题集中在何时,我对其原因感兴趣.

我知道事情是如何运作的.经典的动物,狗,猫的例子总是像魅力一样.

事情是这个代码

int main()
{
    Cat c;
    Sound theSound;
    c.letsDo(&theSound);
}
Run Code Online (Sandbox Code Playgroud)

对我来说似乎很不自然.为什么?

我的意思是,是啊,这样我有我的狗和猫的模型未分化(我第一次用英语BTW这个词),因为真正的implentation是声音类下隐藏,但不只是为了压低你的代码的方式?多态性不足以做这样的事吗?

对我而言,不同之处在于,使用多态性,您必须编辑每个类(但模型保持不变,对吧?)而您只需使用访问者设计模式编辑一个类.

design-patterns visitor-pattern

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

C#中的用户可扩展访问者模式

是否可以在 C# 中创建用户可扩展的访问者模式?(最好是 .net 3.5)

我在库中有一组类,我希望使用访问者模式向其中添加功能。问题是库的用户也可以创建自己的类。这意味着您需要创建一个特殊的访问者来接受新的类类型,但我们的 Accept 方法被设置为接收基本类型。如何让派生类在派生访问者中调用正确的方法。

或者是否有另一种方式来做“如果是这种类型,就这样做”?

一些示例代码:

/* In library */
namespace VisitorPattern.System
{
   interface IThing
   {
      void Accept(SystemVisitor visitor);
      void ThingMethodA(...);
      void ThingMethodB(...);
   }

   class SystemThingA : IThing
   {
      public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
      ...ThingMethods...
   }
   class SystemThingB : IThing
   {
      public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
      ...ThingMethods...
   }
   class SystemThingC : IThing
   {
      public void Accept(SystemVisitor visitor) { visitor.Visit(this); }
      ...ThingMethods...
   }

   class SystemVisitor
   {
      public SystemVisitor(object specialSystemServices) { }
      public virtual …
Run Code Online (Sandbox Code Playgroud)

c# visitor-pattern

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

(嵌套?)多个调度[访客模式]

我在应用程序架构中遇到了障碍.我刚刚开始使用访问者模式在抽象对象上执行特定的算法,这些抽象对象在运行时我不知道.我的问题是我的算法也取决于嵌套抽象类型的类型.

让我说明一下我的意思:

我有一个抽象的DataSource类.从这里我实现了concerete DataSourceReference和DataSourceExplicit类.我还有一个抽象的Report类(反序列化的元数据),我从中实现具体的Report类ReportTypeA和ReportTypeB.创建这些对象时,它们的DataSource可以是任何扩展的DataSource类.

我需要两者,实际的Report类型和DataSource类型,所以我可以相应地执行.我可以使用访问者模式获取协同报告类型,但不知道如何在之后/也为DataSource执行相同操作.

访问报告后我无法访问DataSource,因为我将失去报告的具体类型(因为您必须让它接受基本报告类型:Accept(SomeDataSourceVisitor d,MetaReport m) - 或者为每个可能的报告类型重载,这违背了访客模式的目的.看到我的问题?

有任何想法吗?我不想使用动态,因为它不需要新报表类型的开发人员确保调度程序(访问者)支持新报表.

现行代码:

public abstract class DataSource
{
}

public class DataSourceReference : DataSource
{
    // reference thing(s)
}

public class DataSourceExplicit : DataSource
{
    // explicit thing(s)
}

public abstract class Report
{
    // some shared Report attribute(s)
    // ...

    public DataSource DataSource { get; set; }

    public abstract FinalReport Execute(IReportExecutionDispatcher d);
}

public class ReportA : Report
{
    // ReportA specific attribute(s)
    // ... …
Run Code Online (Sandbox Code Playgroud)

architecture abstraction multiple-dispatch double-dispatch visitor-pattern

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

访客模式和遍历机制

我有一个图形和一组非常简单的访问者,它们对图形的顶点/边缘进行一些计算,例如获得边缘的总重量和漂亮的图形打印.

我想更进一步,让访问者以DFS方式访问图表.

但是,我认为访问者模式应该与遍历机制分开,并且应该使用其他模式(如迭代器)创建遍历方法.我纠正还是错过了什么?

design-patterns graph visitor-pattern

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

boost :: any的访客模式

我找到了这个https://gist.github.com/2945472,但我需要一个不依赖于c ++ 11的实现.我尝试将它转换为仅使用boost,但我遇到了一些麻烦.

这是我想出的:

#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/unordered_map.hpp>

struct type_info_hash {
    std::size_t operator()(std::type_info const & t) const {
        return t.hash_code();
    }
};

struct equal_ref {
    template <typename T> bool operator()(boost::reference_wrapper<T> a,boost::reference_wrapper<T> b) const {
        return a.get() == b.get();
    }
};
struct any_visitor {
    boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref> fs;

    template <typename T> void insert_visitor(boost::function<void(T)> f) {
        try {
            fs.insert(std::make_pair(boost::ref(typeid(T)), boost::bind(f, boost::any_cast<T>(boost::lambda::_1))));
        } catch (boost::bad_any_cast& e) {
            std::cout << e.what() << std::endl;
        } …
Run Code Online (Sandbox Code Playgroud)

c++ boost visitor-pattern boost-any

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

访客模式可以用回调函数替换?

使用这两种技术有什么显着的好处吗?如果有变化,我的意思是访客模式:http://en.wikipedia.org/wiki/Visitor_pattern

以下是使用委托实现相同效果的示例(至少我认为它是相同的)

假设有一组嵌套元素:学校包含包含学生的部门

而不是使用访问者模式在每个集合项上执行某些操作,为什么不使用简单的回调(C#中的Action委托)

说这样的话

class Department
{
    List Students;
}

class School
{
    List Departments;

    VisitStudents(Action<Student> actionDelegate)
    {
        foreach(var dep in this.Departments)
        {
            foreach(var stu in dep.Students)
            {
                actionDelegate(stu);
            }
        }
    }
}

School A = new School();
...//populate collections

A.Visit((student)=> { ...Do Something with student... });
Run Code Online (Sandbox Code Playgroud)

*编辑示例,委托接受多个参数

假设我想通过学生和部门,我可以像这样修改动作定义:动作

class School
{
    List Departments;

    VisitStudents(Action<Student, Department> actionDelegate, Action<Department> d2)
    {
        foreach(var dep in this.Departments)
        {
            d2(dep); //This performs a different process.
            //Using Visitor pattern would avoid …
Run Code Online (Sandbox Code Playgroud)

c# delegates design-patterns visitor-pattern

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

当"if else"/"instance of"不可避免时,除了使用访客模式之外,我们如何改进设计呢?

当我们的对象层次结构纯粹是语义的继承而不是行为的继承时,那么我们不可避免地需要在任何地方编写"instanceof"或"if/else"来进行运行时类型检查.

例如

如果我有一个对象层次结构

Class Function

Class Average extends Function

Class Sum extends Function

Class Max extends Function
Run Code Online (Sandbox Code Playgroud)

如果在这些类中有一个名为calculate()的方法,那么我们没有问题,我们可以利用多态性,这种设计满足LSP.

但是,如果由于某种原因我们不想将此calculate()方法添加到此层次结构中,则这些对象纯粹是对象无状态对象,只表示语义.

然后我们被迫在任何地方编写以下代码:

if (function instanceof Average)
//perform average
else if(function instanceof Sum)
//perform sum
else if(function instanceof Max)
//perform max
Run Code Online (Sandbox Code Playgroud)

上面的代码表明设计不好,因为你在任何地方编写这个代码,这个设计很脆弱,以后很难改变.我想如果数字函数是有限的并且函数的计算在一个地方,这可能是好的取决于复杂性.

到目前为止我所知道的是,要解决上述方法,唯一可行的方法是实现访问者模式,除了使用访问者模式之外,还有其他方法可以解决上述设计吗?

我可以从访问者模式看到的一个问题是访问者模式的accept方法没有返回值,如果accept()方法不能完全满足需求,这有时候不方便.

java design-patterns liskov-substitution-principle instanceof visitor-pattern

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

访客模式(从下到上)

请考虑以下之前,我去我的关于特定问题(例如)代码visitor patternpython:

class Node:
    def __init__(self):
        self.children = []
    def add(self, node):
        self.children.append(node)
    def check(self):
        print("Node")
        return True
    def accept(self, visitor):
        visitor.visit(self)

class NodeA(Node):
    def check(self):
        print("NodeA")
        return True
class NodeB(Node):
    def check(self):
        print("NodeB")
        return True


class NodeA_A(NodeA):
    def check(self):
        print("NodeA_A")
        return True
class NodeA_B(NodeA):
    def check(self):
        print("NodeA_B")
        return True

class NodeA_A_A(NodeA_A):
    def check(self):
        print("NodeA_A_A")
        return False

class NodeRunner:
    def visit(self, node):
        node.check()
        if len(node.children) > 0:
            for child in node.children:
                child.accept(self)

if __name__ == "__main__": …
Run Code Online (Sandbox Code Playgroud)

python design-patterns visitor-pattern python-2.7

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

使用Visitor和Composite模式构建过滤流

我正在使用具有多个叶节点类的复合模式,这些类具有专家操作和访问者模式以允许执行这些操作.在这个例子中,accept为了清楚起见,我省略了所有明显的方法.

interface Command {
    public int getCost();
}

class SimpleCommand implements Command {
    private int cost;

    public int getCost() {
        return cost;
    }
}

class MultiCommand implements Command {
    private Command subcommand;
    private int repeated;

    public int getCost() {
        return repeated * subcommand.getCost();
    }

    public void decrement() {
        if (repeated > 0)
            repeated--;
    }
}

class CommandList implements Command {
    private List<Command> commands;

    public int getCost() {
        return commands.stream().mapToInt(Command::getCost).sum();
    }

    public void add(Command command) {
        commands.add(command);
    }
} …
Run Code Online (Sandbox Code Playgroud)

java design-patterns composite visitor-pattern

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

访客模式中"accept"方法的需要是什么

我期待在访问者模式的解释在这里,显示下面的代码:

public class ShoppingCart {
  public double calculatePostage() {
    PostageVisitor visitor = new PostageVisitor();
    for(Visitable item: items) {
      item.accept(visitor);
    }

public class PostageVisitor implements Visitor {
  public void visit(Book book) {

public class Book implements Visitable{
  public void accept(Visitor vistor) {
    visitor.visit(this);
  }
Run Code Online (Sandbox Code Playgroud)

从JavaScript开发人员的角度来看,该accept方法似乎是多余的,因为代码可以像这样编写:

for(Visitable item: items) {
   // directly call visitor passing an item instead of doing so through `accept` method
   visitor.visit(item);  
}
Run Code Online (Sandbox Code Playgroud)

我是否正确地认为这不起作用,因为编译器不知道visit访问者的哪个重载方法要执行?

据我所知,编译器了解visitvisitorwith 上执行哪个方法,accept …

java visitor visitor-pattern

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