问题标签 [visitor-pattern]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
107 浏览

java - 如何修改包外的预定义包方法?

假设我有一个名为“animal”的包,其中包括 Animal 父类,Cat 扩展自 Animal,Dog 也扩展自 Animal。然而,Animal 是这样设计的:

Cat & Dog 类遵循以下结构:

他们每个人都有这样的方法drinkWater():

我现在要做的是创建一个动物的“链接列表”,每个动物都按顺序喝水。但是,假设一只猫喝了 n 量的水,它会将 n+1 量的水传递给它。next

我的目的是找到一个解决方案来克服“不接触原始动物包装,而是改变每个动物的饮水行为”的问题。我带着一个“著名的”天真的解决方案来了一个类:

然后,我开始研究。因为这看起来确实是快速而肮脏的解决方案。

所以,我发现了一种叫做“访客模式”的设计模式。好吧,很酷的模式解决了双重调度的问题,但我这边有一个问题:可访问接口(声明了 accept() 方法)应该由原始动物“实现”。但是,我的目标是“不要对原始动物包装进行任何修改,而是要改变饮水行为”。我很确定我错过了一些东西。

那么,您认为稍微修改一下,访客模式仍然可以工作还是其他模式/解决方案会更好?谢谢。

0 投票
3 回答
1245 浏览

c++ - 没有虚拟方法的设计模式“容器访问者”?

我正在开发一个应用程序的设计,我想我可能会应用某种访问者设计模式,但事实证明这并不是我想要的。也许有人可以指出我在这种情况下需要的变体?

我的大部分代码都有一个模板参数“ContainerType”,例如

当前,通常共享许多数据字段的“容器”数量虽小但数量不断增加。

Container1 和 Container2 现在用作 MyClass(和其他)的模板参数,其中 A、B、C 是一些已定义的类。(我有一些方法可以get<A>(container)访问包含的数据。这种设计提供了编译时安全性,MyClass 可以与包含所需类型的所有容器类型一起使用。)

现在我想添加“如果容器包含某种类型(例如A),则执行某些操作,否则不执行任何操作”的功能。

这可以通过看起来像访问者的东西来完成(但请注意,没有使用虚拟方法)。它甚至允许“如果容器包含 A 执行此操作,如果它包含 D 执行其他操作,否则不执行任何操作”。这可以通过

这是我想要的,但我正在寻找一种更好的方法来做到这一点,因为这里显示的实现需要为每个 ContainerType 实现接受。如果有人从accept方法派生但忘记扩展accept方法,事情就会变得糟糕Container1ContainerBase<D>更糟糕的是,我需要一个 const 和 non-const 版本的 accept 并且一些容器包含 >5 种类型,所以看起来也不好看。

ContainerBase<T>所有容器类都是通过多次继承构建的,所以我想知道是否可以使用这种结构来实现 ContainerBase 类中的接受(和接受(..)常量)?我已经看过 Lokis 类型列表,但我不知道如何在这里使用它们。你有什么主意吗?

或者是否有可能在没有访问者结构的情况下做这件事?

非常感谢!

编辑:我知道我可以使用 RTTI,但如果可能的话,我想避免运行时检查和虚拟方法。

0 投票
2 回答
82 浏览

user-interface - 以正确的顺序进行 Blitting - 访问者问题

我正在设计一个简单的 GUI。我有小部件,它有孩子和一个父母。每个 Widget 都是一个 Composite 对象,带有一个 WidgetComposite 对象的向量。其中一个 WidgetComposites 是 PaintingBehaviour,但 Widget 并不知道它本身。

为了显示我的窗口,我使用了一个访问者,称为 ScreenVisitor。当调用访问者时,会发生以下情况:

第一个小部件 WidgetScene 迭代其每个小部件并调用“accept(Visitor* v)”方法。然后,每个小部件接受访问者,然后迭代其子级。

例如,这是访问者必须接受的对象列表(按照发生的顺序)。

现在,我的问题很简单:我希望将每个 Widget 绘制在其父级上。你将如何进行?我试过一棵树,但我总是遇到同样的问题:当我必须在层次结构中上升时(例如,在显示 child3 之后,当我必须显示 child4 时)我不知道如何获得正确的父母。

我正在用 C++ 编码,但这个问题不是特定于语言的。

你有什么想法 ?提前致谢 !

0 投票
3 回答
4762 浏览

java - java中的通用访问者模式

以下使用泛型的访问者模式的 Java 实现是否足够通用?(我想是的)。

可以通过某种方式改进吗?使用匿名类可以轻松调用是很重要的。谢谢。

(使用示例):

定义:

0 投票
1 回答
207 浏览

java - 关于通过 PropertyChangeSupport 更新 Swing GUI 的设计问题

过去,我使用 PCS 来更新显示某些字段的 Swing 元素,并且一切都按预期工作。然而,我现在面临着一个相对复杂(换句话说,设计非常糟糕)的 UI,它显示了很多字段。数据更新成束出现(一个包含大约 1,000 个字段的新值的网络数据包),我想知道处理此类事情的正确方法是什么。

我主要担心的是,每当数据包到来时,都会触发 1,000 个 PropertyChangeEvent,从而导致 1,000 个 .repaint()(或 .revalidate() 或其他)。更谨慎的方法似乎是做类似“gui.stopRepainting(); fireAllThePropertyEvents(); gui.restartPainting();”之类的事情。有没有办法做到这一点,或者有没有更好的方法来处理这个?

0 投票
5 回答
4004 浏览

design-patterns - 访问者模式的变体:为什么不将第二次调度移动到访问者的 `Visit` 方法中?

介绍

显然,我的整个程序员生涯都在做一个“非正统”的访问者模式。

是的,我从访问者的方法中分派到一个具体的复合元素访问Visit方法。

我想这就是我学习它的方式,但现在我找不到任何例子,我学习它的来源也不见了。

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

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

例子

这是基本的复合/访客模型:

请注意,访问者类现在负责第二个基于类型的调度,而不是规范版本,例如,Foo将负责它并且将具有:

现在,为了防守...

优势一

假设我们要添加一个新的 CompositeElement 类型:

为了在访问者模型中适应这种新元素类型,我只需要对 BaseVisitor 类进行更改:

诚然,这是一个小问题,但它似乎确实简化了维护(也就是说,如果您不介意大ifswitch声明)。

优势二

假设我们想在一个单独的包中扩展组合。我们可以在不修改的情况下适应这一点BaseVisitor

拥有这种结构使我们能够打破为了容纳扩展的 CompositeElement 类型而BaseVisitor需要拥有的依赖关系。VisitExtended

结论

在这一点上,我还没有实现足够长的访问者模式或维护它足够长的时间,以使任何不利因素对我造成影响。显然,维护一个大的 switch 语句是一种痛苦,并且会影响性​​能,但是我不确定它们是否超过了保持BaseVisitor对扩展的依赖的灵活性。

请权衡您对不利因素的看法。

0 投票
5 回答
2895 浏览

c++ - C++:对访问者模式的质疑

我知道访客模式是什么以及如何使用它;这个问题不是这个问题的重复


我有一个库,其中放置了我编写的大部分可重用代码,并链接到我的大多数项目。

通常我需要向某些类添加特性,但没有将这些新特性添加到库中。让我用一个真实的例子:

在这个库中,我有一个类,由和Shape继承。CircleShapePolygonShapeCompositeShape

我现在正在开发一个图形应用程序,我需要在其中渲染这些Shape,但不想render在核心Shape类中放置一个虚函数,因为我使用的一些项目Shape不进行任何渲染,而其他图形项目可以使用不同的渲染引擎(我在这个项目中使用 Qt,但对于游戏我会使用 OpenGL,因此该render函数需要不同的实现)。

当然,最有名的方法是使用访问者模式,但这让我产生了一些疑问:

任何库的任何类都可能需要像我Shape一样进行扩展。大多数公共图书馆(几乎全部)都不提供对访问者模式的任何支持;为什么?我为什么要?

访问者模式是一种在 C++ 中模拟双重调度的方法。它在 C++ 中不是原生的,需要显式实现,这使得类接口更加复杂:我认为该applyVisitor函数不应该与我的类函数处于同一级别,我认为这就像破坏抽象。

显式向上转换Shapedynamic_cast昂贵,但对我来说它看起来像一个更清洁的解决方案。


所以我该怎么做?在我所有的库类中实现双重调度?如果提供的库Shape不是我的,而是在互联网上找到的一些 GPL 库怎么办?

0 投票
1 回答
1160 浏览

java - 如何在 Java 中为 DAG 结构创建迭代器包装器?

我想在数据结构上有一个迭代器。现在我不知道数据结构是什么,也许它是一个 DAG(有向无环图),但也许它也可能是一个链表。所以我想把它包装成一个迭代器,现在不要考虑特定的数据结构。

我知道如何使用类似递归的访问者来访问 DAG,但我无法找出一个简单而干净的结构来实现迭代器方法next()hasNext().

在迭代器内部,我创建了一个当前节点实例,并使用 for 循环遍历所有子节点,然后返回父节点。需要一个“已访问”标志。所以我DagElement有这些更多的属性:

我不认为这是一个干净的解决方案。

有什么建议吗?

0 投票
2 回答
4932 浏览

design-patterns - 模式策略、访问者和模板方法有什么区别?

我正在上课,我们刚刚了解了这些设计模式。但是我看不出它们之间有什么区别。它们听起来很像,在抽象类之上创建具体类。有人可以帮我消除这个疑问吗?谢谢 (:

0 投票
3 回答
439 浏览

java - 谁能指导我看一篇描述访问者设计模式的优秀文章

如果代码是用 Java 编写的,任何人都可以指导我阅读一篇描述访问者设计模式的优秀文章。

谢谢