使用访客设计模式的充分理由是什么?

发布于 2024-09-19 04:42:59 字数 535 浏览 6 评论 0原文

在你告诉我已经有一个类似的问题之前,是的,我知道,我已经读过 。 但问题集中在何时,我感兴趣的是为什么

我明白事情是如何运作的。经典的动物,狗,猫示例总是很有魅力。

问题是这段代码

int main()
{
    Cat c;
    Sound theSound;
    c.letsDo(&theSound);
}

对我来说看起来很不自然。为什么?

我的意思是,是的,这样我的狗和猫模型无差别(顺便说一句,我第一次在英语中使用这个词),因为真正的实现隐藏在 Sound 类下,但这不仅仅是一种减轻代码重量的方法?多态性不足以做这样的事情吗?

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

Before you tell me that there is already a similar question, yes, i know, I've read it.
But the question there focuses on when, I'm interested in why.

I get how the things work. The classic animal,dog,cat example always works like a charm.

The thing is this code

int main()
{
    Cat c;
    Sound theSound;
    c.letsDo(&theSound);
}

seems so unnatural to me. Why?

I mean, yeah, this way I have my Dog and Cat models undifferentiated (first time I ever use that word in english btw) because the real implentation is hidden under the Sound class but isn't that just a way to weigh down your code? Isn't polymorphism enough to do something like this?

To me the difference is that with polymorphism you have to edit each class (but the model stays the same, right?) whereas you have just to edit one class with the visitor design pattern.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

长梦不多时 2024-09-26 04:42:59

访问者模式允许您做一些仅依靠多态性无法做到的事情:处理意外的用例。如果您正在编写一个库,这是很重要的一点。让我详细说明一下:

考虑一个使用访问者模式的经典示例,即对某些 的节点进行操作抽象语法树。要添加一些细节,比如说,您刚刚为 SQL 编写了一个解析器库,它接受字符串,解析它们,并返回在输入中找到的内容的 AST。除非您可以预测客户端代码可能具有此类 AST 的所有潜在用例,否则您必须提供一种“通用”方式来遍历 AST。提供类似 DOM 的访问器函数(getNodeTypegetParentNodegetPreviousNode)是一种方法。这里的问题是,这给图书馆的客户带来了沉重的负担,因为他们需要自己进行调度。更重要的是,他们需要非常详细地了解每种可能的节点类型遵循哪些指针:

void 
walk_tree(AstNode* node) 
{
    switch( node->getNodeType() ) {
    case SELECT_NODE:
        for( AstNode* child = node->getFirstChild(); child; child = child->getNextNode() ) {
             walk_tree(child);
        }
        break;
    ...
    }
}

访问者模式将这种负担从客户端转移到库中。

The visitor pattern allows you to do something, which simply relying on polymorphism does not: work with unanticipated use cases. If you are writing a library, this is an important point. Let me elaborate:

Consider a classical example for the use of the visitor pattern, namely, the operation on the nodes of some abstract syntax tree. To add some details, say, you have just written a parser library for SQL, which takes strings, parses them, and returns an AST for the stuff it found in the input. Unless you can anticipate all potential use cases your client code might have for such an AST, you have to provide a "generic" way to walk the AST. Providing DOM-like accessor functions (getNodeType, getParentNode, getPreviousNode) is one way. The problem here is, that this puts a heavy burden on the clients of your library, because they need to do the dispatch themselves. Even more, they need to know in great detail, which pointers to follow for each possible node type:

void 
walk_tree(AstNode* node) 
{
    switch( node->getNodeType() ) {
    case SELECT_NODE:
        for( AstNode* child = node->getFirstChild(); child; child = child->getNextNode() ) {
             walk_tree(child);
        }
        break;
    ...
    }
}

The visitor pattern moves this burden from the client into the library.

慢慢从新开始 2024-09-26 04:42:59

假设您在不属于您的库中定义了一些基本内容,并且您需要扩展它。就像:

// In base lib:
interface ISomething {
    void DoSomething();
}

class Something1 : ISomething {
    // ...
}

class Something2 : ISomething {
    // ...
}

多态性允许您定义可以执行操作的新事物:

// In your lib:
class MySomething : ISomething {
}

现在基础库可以与您的 MySomething 一起使用,就像它已经定义了它一样。它让您做的是添加新的操作DoSomething 是我们可以使用 ISomething 做的唯一事情。访客模式解决了这个问题。

缺点是使用访问者模式会降低您定义新类型的能力,就像我们刚才展示的那样。大多数语言允许您轻松添加操作或类型,但不能同时添加两者,这一事实称为表达式问题< /a>.

访问者模式是一种很酷的模式,但除了实现编译器之外,我从未真正发现需要它。

Let's say you've got some basic stuff defined in a library you don't own, and you need to extend it. Like:

// In base lib:
interface ISomething {
    void DoSomething();
}

class Something1 : ISomething {
    // ...
}

class Something2 : ISomething {
    // ...
}

Polymorphism lets you define new things you can perform operations on:

// In your lib:
class MySomething : ISomething {
}

And now the base lib can work with your MySomething as if it had defined it. What it doesn't let you do is add new operations. DoSomething is the only thing we can do with an ISomething. The Visitor pattern addresses that.

The downside is that using the visitor pattern costs you the ability to define new types like we just showed. The fact that most languages let you either add operations or types easily, but not both, is called the expression problem.

The visitor pattern is a cool one, but I've never actually found a need for it outside of implementing compilers.

欲拥i 2024-09-26 04:42:59

访问者模式非常有用。

使用它至少有三个重要原因:

  1. 减少数据结构更改时仅略有不同的代码扩散。

  2. 将相同的计算应用于多个数据结构,而不更改实现计算的代码。

  3. 将信息添加到旧库而不更改旧代码。

请查看 我写过一篇关于此的文章

干杯

The Visitor Pattern is very useful.

There are at least three big reasons for using it:

  1. Reduce proliferation of code which is only slightly different when data structures change.

  2. Apply the same computation to several data structures, without changing the code which implements the computation.

  3. Add information to legacy libraries without changing the legacy code.

Please have a look at an article I've written about this.

Cheers

つ可否回来 2024-09-26 04:42:59

当我有一棵对象树并且需要以多种方式打印内容时,我使用了访问者模式。逗号分隔、XML,等等。我没有为每种输出格式向树类添加新的打印方法,而是使用访问者模式并创建了 CommaSepVisitor、XMLVisitor 和 HTMLVisitor 类。当我添加更多访问者类型时,树代码从未改变,因此我从未引入错误。来访者本身很容易写。

I used the visitor pattern when I had a tree of objects and needed to print the contents in numerous ways. Comma-sep, XML, whatever. Instead of adding to the tree class a new print method for each output format, I used the visitor pattern and created CommaSepVisitor, XMLVisitor, and HTMLVisitor classes. The tree code never changed as I added more Visitor types so I never introduced bugs. The visitors themselves were easy to write.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文