我正在努力实现从“hello world”等效功能程序到更多真实应用程序的跨越。
当我来自Java世界并且已经接触到它的所有设计模式时,我的建模过程仍然非常面向Java(例如我认为* Managers,* Factory,* ClientFactory,* Handler等)< / p>
一次改变我的思维过程将很难,所以我希望得到一些关于如何用功能语言建模以下场景(以OO方式描述)的指针。
像Clojure / Haskell这样的函数式语言(或者像Scala这样的混合函数)的例子会有所帮助。
无状态请求处理程序
E.g。是一个Servlet。它本质上是一个请求处理程序,使用doGet,doPost等方法。如何用函数式语言模拟这样的类?
Orchestrator类
这些课程本身不做任何事情,只是协调整个过程或工作流程。它们提供多个入口点API。
E.g。 OrderOrchestrator协调多步骤工作流程,从支付工具验证,购物车管理,付款,发货启动等开始。
他们可能会维持一些自己的内部状态,这些状态由付款,发货等不同步骤使用。
ClientFactory模式
假设您已编写了一个客户端,该客户端用于客户端用于记录有关其服务的流量数据的LogService。客户端在您管理的存储桶和帐户下记录S3中的数据,并提供其他服务,如报告和分析此数据。 您不希望您的客户担心提供AWS账户信息等配置信息,因此您提供了一个ClientFactory,它根据是用于测试还是生产目的来实例化相应的客户端对象,而无需客户提供任何配置。例如。 LogServiceClientFactory.getProdInstance()或LogServiceClientFactory.getTestInstance()。
这样的客户端如何用函数式语言建模?
Builder Pattern和其他Fluent API设计
客户端库通常提供构建器来创建具有复杂配置的对象。有时API也很流利,可以轻松创建。 Fluent API的一个例子是Mockito API:Mockito.when(A.get())。thenReturn(a)IIRC这是通过返回逐步限制的构建器来内部实现的,以允许开发人员编写此代码。
这在函数式编程世界中是否与此相似?
数据存储区实例
假设您的代码库使用来自多个地方的ActiveUserRegistry中存储的数据。您只需要存在此注册表的一个实例,并且整个代码库都可以访问此注册表。因此,您提供了一个ActiveUserRegistry.getInstance(),它保证所有代码库都访问实例(假设该实例是线程安全的等等)。
如何在功能设置中管理?我们是否必须确保在整个代码库中传递相同的实例?
答案 0 :(得分:2)
以下是要开始的事情:
无状态请求处理程序
Clojure:Protocols
Haskell:输入类
Orchestrator类
州议员
ClientFactory模式
LogServiceClientFactory是一个Module,getProdInstance和getTestInstance是模块中的函数。
Builder Pattern和其他Fluent API设计
功能组合
数据存储区实例
Clojure:使用原子的函数(用于存储和使用单个实例)
Haskell:TVar,MVar
答案 1 :(得分:2)
我对这些Java风格的结构并不熟悉,但我会采取一些措施来回答:
无状态请求处理程序
这些也存在于功能世界中。函数可以轻松地填充此角色,即使是从请求到响应的函数这么简单。 Play框架使用更强大的功能,特别是从Request
到Iteratee
(类型(RequestHeader) ⇒ Iteratee[Array[Byte], SimpleResult]
)的功能。 Iteratee
是一个实体,可以在收到输入时逐步消耗输入(Array[Byte]
)并最终生成响应(SimpleResult
)以回馈给客户端。请求处理程序函数是无状态的,可以重用。 Iteratee
也是无状态的 - 为每个块提供它的结果实际上是为了获得新的Iteratee
,然后将其送入下一个块。 (我真的过于简单了,它使用Futures,完全没有阻塞,并且具有有效的错误处理 - 值得一看,感受功能样式代码可以为这个问题带来的强大和简单性。)
Orchestrator类
我不熟悉这种模式,所以请原谅我,如果没有意义的话。有一个巨大的可变对象被传递是一种反模式。在功能代码中,将有单独的数据类型来表示需要在进程的每个阶段之间传递的数据。这些数据类型是不可变的。
至于组织其他事情的事情,请查看Akka以及一个演员如何监视其下的其他演员,处理错误或根据需要重新启动它们。
Builder Pattern和其他Fluent API设计
功能程序具有这些功能,并将它们归结为逻辑结论。功能代码允许非常强大的DSL。举个例子,查看一个解析器组合库,可以是Scala标准库中的一个,也可以是Haskell的一个库。
ClientFactory模式和数据存储区实例
我不认为这在功能代码中有任何不同。你有一个单身人士,或者你做了适当的依赖注入。工厂模式也用于功能代码,虽然一流的功能使许多设计模式太微不足以值得命名(来自GoF:工厂,工厂方法,命令,至少一些战略和模板的实例通常只是是功能)。
答案 2 :(得分:1)
查看Scala和Clojure中的函数式编程模式:http://pragprog.com/book/mbfpp/functional-programming-patterns-in-scala-and-clojure。
它应该完全符合你的需要。