代码之家  ›  专栏  ›  技术社区  ›  Wonay

scala:UI对象/渲染器的设计模式

  •  1
  • Wonay  · 技术社区  · 7 年前

    有什么好的设计 renderer 和 object .

    我做了一些尝试,但我的代码现在真的很难看。

    假设我有个班 room 以及一个应该处理呈现它的类。

    • 谁应该打电话 renderer.render(room) 还是应该这样?
    • 我应该拥有 world.renderRoom() ?
    • 或者我应该 room.renderWith(renderer) ?

    如何构建简单的单元测试,比如 renderer.render(room, userInteraction)

    那么回报应该是什么呢?

    world.renderRoom().interact().... ?

    如你所知,我不知道该做什么哈哈。

    我有几年编写软件的经验,但我正在尝试 ScalaZ 努力做到更多 functional-programming -就像;这对我来说是新的。

    谢谢你

    2 回复  |  直到 7 年前
        1
  •  2
  •   Arnon Rotem-Gal-Oz    7 年前

    呈现屏幕并不是纯粹的函数,因为它有副作用。读上 IO monad .

    您会发现大多数(如果不是全部)示例都围绕println和readln,但同样的原则也适用。在scalaz的上下文中,请看一下 ZIO .

    如果正如Tim在注释中建议的那样,render是纯函数,那么我建议render是模型render(room)的函数,room state是操作的倍数。 newRoomState=actions.foldLeft(oldRoomState)(state,action => someFunction(s,a)) (粉刷墙壁,加沙发什么的)看 SAM pattern . 以及接受渲染的世界(平面图/在多个渲染上减少)?!)是保证IO Monad的部分)

        2
  •  2
  •   Tim    7 年前

    你似乎在问一些不同的问题,这使得你很难回答,除非用非常一般的方式。

    不要向数据对象添加呈现代码,因为这会破坏关注点的分离。典型的OO示例 Shape 用A类 draw 方法是很好的教学方法,但它将有关形状的数据(如边数)与特定的绘制方法相结合。相反,创建一个函数 render(s: Shape) 使用中的数据 形状 以特定方式绘制(二维、三维填充、坐标列表等)。

    让你的 render 代码函数化,以便它返回呈现的数据,而不是作为副作用调用呈现库。渲染库需要具有功能性并返回渲染结果,而不是直接绘制到屏幕上。

    将渲染库传递给 提供 函数(如 implicit 参数),而不是使用全局对象。这允许您使用模拟渲染器测试渲染,并且无论如何是一种更灵活的设计。但你还是需要不同的 提供 用于不同输出设备或样式的功能。

    将渲染与渲染组件的组合分离,以便可以独立测试它们。

    以功能性方式构建整个图像,然后进行单个非功能性操作以显示新图像(通过替换当前图像)。

    使用用户交互创建具有更新的 room 然后重新渲染整个场景。

    DR

    val room = Room(width, length, height)
    val room3D = render(room, render3D)
    val house = compose(room3d, ..., compose3D)
    
    screen.display(house)
    
    推荐文章