问题标签 [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 回答
584 浏览

c# - 有没有一种简单的方法可以在 C# 中模拟 Objective-C 类别?

我有一个以前从未遇到过的奇怪的设计情况......如果我使用的是Objective-C,我会用类别来解决它,但我必须使用C# 2.0。

首先,一些背景。我在这个类库中有两个抽象层。底层实现了用于扫描内容的组件的插件架构(抱歉,不能比这更具体)。每个插件都会以某种独特的方式进行扫描,但插件也会因它们接受的内容类型而异。由于与本次讨论无关的各种原因,我不想通过插件接口公开泛型。因此,我最终得到了 IScanner 接口和每种内容类型的派生接口。

顶层是一个方便的包装器,它接受包含各个部分的复合内容格式。不同的扫描器将需要复合的不同部分,具体取决于他们感兴趣的内容类型。因此,我需要具有特定于每个 IScanner 派生接口的逻辑,用于解析复合内容,查找所需的相关部分。

解决这个问题的一种方法是简单地向 IScanner 添加另一个方法并在每个插件中实现它。但是,两层设计的重点是让插件本身不需要了解复合格式。解决这个问题的蛮力方法是在上层进行类型测试和向下转换,但这些都需要小心维护,因为将来会添加对新内容类型的支持。在这种情况下,访问者模式也会很尴尬,因为实际上只有一个访问者,但不同访问类型的数量只会随着时间的推移而增加(即——这些是访问者适用的相反条件)。另外,当我真正想要的是劫持 IScanner 的单次调度时,双重调度感觉有点过头了!

如果我使用的是 Objective-C,我只需在每个 IScanner 派生接口上定义一个类别,然后在其中添加 parseContent 方法。类别将在上层定义,因此插件不需要更改,同时避免了类型测试的需要。不幸的是,C# 扩展方法不起作用,因为它们基本上是静态的(即——绑定到调用站点使用的引用的编译时类型,而不是像 Obj-C 类别那样与动态调度挂钩)。更不用说,我必须使用 C# 2.0,所以我什至无法使用扩展方法。:-P

那么在 C# 中是否有一种干净简单的方法来解决这个问题,类似于如何使用 Objective-C 类别来解决这个问题?


编辑:一些伪代码有助于使当前设计的结构清晰:


编辑:澄清一下,我已经对这个设计进行了很多思考。我有很多原因,其中大部分我无法分享,为什么它是这样的。我还没有接受任何答案,因为虽然很有趣,但他们回避了最初的问题。

事实上,在 Obj-C 中,我可以简单而优雅地解决这个问题。问题是,我可以在 C# 中使用相同的技术吗?如果可以,如何使用?我不介意寻找替代品,但公平地说,这不是我问的问题。:)

0 投票
4 回答
7548 浏览

c# - 在 C# 中使用带有泛型的访问者模式

我想知道下面的访问者模式是否可以接受。从 Accept() 或 Visit() 调用返回时我感到有点不舒服 - 这是该模式的适当用法吗?如果不是,为什么不呢?

注意:为长代码示例道歉,似乎有必要了解我正在做的事情,因为访问者似乎总是有点参与......

0 投票
5 回答
1762 浏览

design-patterns - 为什么访问者负责在访问者模式中枚举孩子?

根据我找到的代码,似乎需要访问者知道访问对象的结构并调用所需的子对象。在某些情况下,即使访问的类被修改,访问者仍希望继续工作,这似乎有点笨拙。

我想真正的问题是:它们是由访问代码而不是访问代码完成枚举的模式吗?

0 投票
3 回答
214 浏览

visitor-pattern - 在访问者模式中应该如何传递“位置”信息?

假设我有这样的访客

其中 AChild 和 BChild 可以是完全相同的类型,但访问代码需要区分它们(它需要在 AChild 和 BChild 上进行不同的操作)。做这个的最好方式是什么?

  • 在访问者中设置状态并在下次调用时检查它
  • 将不同的访客传给每个孩子
  • 其他?

对不起,我第一次是倒着做的(当前AcceptVisit)。它现在匹配Wikipedia 中显示的模式

所有访问方法如下所示:

0 投票
3 回答
2427 浏览

c++ - 节点的迭代层次结构 - 访问者和复合?

假设我有一个节点集合,稍后用于我的 Renderer 类。然后我有一个可以访问节点或整个集合的访问者类。这很简单,因为我的节点集合只是 std::list 的包装器,几乎没有额外的方法。

问题是我想要一个树状结构的节点(而不是简单的列表),所以一个节点可以有一个父节点和 n 个子节点。这会很方便,因为我希望能够将一个节点传递给我的渲染器并渲染该节点“下方”的所有内容。答案可能是复合。

如何同时使用访客和复合?我读过它通常是一个很好的组合,但我的实现看起来很糟糕......我错过了某事。

0 投票
3 回答
332 浏览

count - 如何在 Web 应用程序中创建可靠且强大的页面查看计数器?

我想统计一个网页上的访问量,这个页面代表了我模型的一个元素,就像 Stack Overflow 问题页面浏览量一样。

如何以可靠(一次访问,一次综合浏览,无重复)和稳健(考虑性能,而不仅仅是新表属性“visits_count”)来做到这一点

0 投票
3 回答
269 浏览

c# - 仅向每个唯一访问者提供一次功能

我写了一个留言板作为我的第一个 ASP.NET 项目。到目前为止,它似乎运作良好。但是,我拥有的功能之一是每封邮件都有垃圾邮件评级。它只是查看者将邮件标记为垃圾邮件的次数除以查看邮件的总次数。这个想法是允许用户在他们选择这样做时忽略具有高垃圾邮件评级的邮件。

然而,整个系统可以被垃圾邮件发送者简单地查看他自己的消息并刷新很多次,这将增加消息被查看的次数。连续多次将邮件标记为垃圾邮件的人也可以阻止它。我需要一种方法来确定特定访问者是否已经查看了特定消息,以及确定特定用户是否已经将特定消息标记为垃圾邮件的方法。

我不想要求注册 - 我希望任何人都能够查看或发布消息。我一直在考虑的两个想法是,当访问者进入网站时设置一个 cookie,以便我可以跟踪他们,或者创建一个新的数据表,在用户查看邮件或将其标记为垃圾邮件时记录用户的 IP 地址。其他人能想出更好的方法吗?.NET 是否有任何内置功能可以帮助我确定访问者是否是第一次查看页面?

0 投票
4 回答
4538 浏览

asp.net - 实施访客计数器

我是一个新手,正在使用带有 C# 2005 的 ASP .Net 2.0 开发一个网站。我想添加一个工具来计算编号。我网站的访问者。我已经收集了使用 Global.asax 添加此功能的基本信息。我通过在 system.web 部分下添加“”行对 Web.config 进行了修改。

我正在使用一张桌子来记录访客人数。但我不知道如何完成任务。我的默认 Global.asax 文件带有不同的部分 Application_Start、Application_End、Application_Error、Session_Start 和 Session_End。我试图在 Application_Start 部分中提取计数器的当前值并将其存储在全局变量中。我将增加 Session_Start 中的计数器并将修改后的值写入 Application_End 中的表。

我曾尝试使用公共子例程/函数。但是我应该把这些子程序放在哪里呢?我试图在 Global.asax 本身中添加子例程。但是现在我遇到了错误,因为我无法在 Global.asax 中添加对 Data.SqlClient 的引用,并且我需要对 SqlConnection、SqlCommand、SqlDataReader 等的引用来实现这些功能。我必须为每个子例程添加类文件吗?请指导我。

我还想对我的网站实施跟踪功能,并存储我的网站访问者的 IP 地址、使用的浏览器、访问日期和时间、屏幕分辨率等。我该怎么做?

等待建议。

拉利特·库马尔·巴里克

0 投票
3 回答
829 浏览

c# - 访客模式,无需强制转换

我有一个关于访客模式的问题,我目前有两个程序集。我的第一个程序集包含几个接口。

我的第二次集会

我想要做的是避免需要在 ContainerVisitor 类中进行转换,我想直接引用 Container。我无法将接口 INodeVisitor 接口更改为使用 Container。有任何想法吗?我应该投吗?

干杯

罗汉

0 投票
1 回答
1418 浏览

java - 一般递归自类型的值的Java字段类型?

给定一个基类定义递归自类型的类层次结构:

我如何声明另一个类(它在 T 中不应该是通用的,因为这样的 T 可能在对象的生命周期内变化)具有可以包含 A 的任何子类的字段?

以下不起作用:

-- 问题结束 --

我注意到许多 StackOverflow 成员倾向于用“你为什么首先这样做?”来解决某些难题。以下是我使用这种模式的理由——您可以注意到 Java 标准库在其 Enum 类的定义中也使用了递归自类型:Enum<E extends Enum<E>>. 这个问题可以类似地被问为“如何定义类型的字段Enum<?>

理由示例:

与子类:

绑定到并行类层次结构:

并且随着 Bifyer 接口的实现管理的 B 实例的生成:

此接口的实现可能会为 B 返回 BSub1 或 BSub2。这本质上是访问者模式的应用程序,其中 Bifyer 是访问者,但与标准访问者不同,accept 方法返回一个值而不是 void。这提供了一个模块化框架,其中可以指定不同的 Bifyer 实现来为 Bify 方法提供替代行为和返回类型 - 例如为 B 的每个子类提供一个。