2

我想创建一个由三个代理组成的简单“多代理”系统。对于每个代理,都会创建一个封装邮箱处理器的类型。所有代理(位置、id 等)和功能(sendMessage、move)都有共同的属性,并且代理因邮箱处理器的实现(如何处理消息)而彼此不同。此外,它们可能因特定于特定代理的其他功能而有所不同。每个代理还应包含(作为其属性之一)其他代理的列表,它将向其发送消息。这是一个非常简单的模型,我计划在此基础上使用 F# 中的邮箱处理器。

在 OOP 中,这意味着创建一个代理接口(或抽象类),并且所有特定的代理都将从该接口继承并具有自己的实现。

我知道 OOP 在 F# 中是可能的,但我宁愿坚持纯函数式设计。但是,在我看来,在这种情况下,OOP 是最合适的方法。如果您能给我关于功能(F#)设计的任何想法,我会很高兴?谢谢你。

4

3 回答 3

16

首先,F# 中的函数式风格面向对象的风格并没有真正的冲突。

  • 函数式风格包括使用不可变类型、没有副作用的纯函数和 F# 数据类型,如可区分联合、函数等。

  • 面向对象的风格更侧重于如何组织代码(使用类和接口),但代码仍然可以是纯函数式的,而不使用任何可变状态。

在基于代理的系统中,在代理的实现中使用函数式风格是很有意义的,但使用类来组织代理。我认为这可能是 F# 中的最佳实践(另请参阅这篇关于 MSDN 上封装 F# 代理的文章)。

在您的示例中,您说代理保留了它向其发送消息的其他代理的列表。有一些替代方案值得考虑(如果你想避免接口):

  • Expose an F# event (Event<'T>). This way, the agent simply exposes a notification and does not have to explicitly manage a list of other agents (and this design also allows other types of subscribers).

  • Keep a list of functions. If you just need to send messages to other agents, then you essentially need just an interface with a single method. In that case, you could keep a list of functions such as
    Message -> unit.

I generally prefer exposing events - this way, the system is less tightly coupled and you can more easily compose agents in various ways (they do not have to implement a specific interface to be composed). This article discusses agent-based architectures from a higher-level perspective, and may be useful too.

于 2013-02-04T14:39:53.403 回答
4

为什么要坚持纯功能设计?F# 允许功能和OOP 原则的干净组合,我将利用这两种机制并利用语言的力量。

如果你想结合功能和 OOP 方面,我会先让你的对象不可变。因此,您正在使用对象,但在功能范式中。

于 2013-02-04T13:57:20.963 回答
2

您提出了 OOD,OOP 解决方案似乎是最自然的,这是否令人惊讶?

如果您用流程和数据转换来重写设计描述,那么它自然会作为 FP 设计而失败,并且在具有许多类的 OO 中听起来真的很尴尬。事实上,对数据类型或需要进行哪些转换的描述几乎为零。乍一看,我会说代理是三个参数的函数:邮箱、消息处理程序(或消息处理程序列表)和要联系的其他代理邮箱列表。如果将来的调度基于消息,那么消息处理程序是两个参数的函数。邮件和邮箱列表。

于 2013-02-04T14:25:23.017 回答