实施策略模式的函数式方法

2024-05-07

我正在尝试解决一个处理从一种温度单位到另一种温度单位(摄氏度、开尔文、华氏度)转换的问题。

在Java中,我需要创建一个接口并提供多个实现来封装输入类型并将结果作为输出类型的单元返回。例如开尔文到摄氏度或摄氏度到华氏度等。我已经在 scala 中将我的代码重构为以下内容,但我仍然觉得它打破了开放封闭原则,因为如果我需要添加另一种类型,我需要更改现有代码。任何建议保持代码功能并遵守开放封闭原则 请忽略转换逻辑

    object TempConverter extends App {

  object UnitType extends Enumeration {
    type EnumType = Value
    val cel, fah, kel = Value
  }

  def convert(x: Double, i:UnitType.Value,o:UnitType.Value) = {
    strategy(i,o)(x)
  }

  def strategy(inputType: UnitType.Value, outputType: UnitType.Value) = {
    inputType match {
      case UnitType.cel => celsius(outputType)
      case UnitType.kel => kelvin(outputType)
      case UnitType.fah => fahrenheit(outputType)
    }
  }


  def celsius(outputType: UnitType.Value) = {
    outputType match {
      case UnitType.fah => x: Double => x * 1.8 + 32
      case UnitType.kel => x: Double => x * 1.8 + 32
    }
  }

  def kelvin(outputType: UnitType.Value) = {
    outputType match {
      case UnitType.cel => x: Double => x - 273.5
      case UnitType.fah => x: Double => x * 1.8 + 32
    }
  }

  def fahrenheit(outputType: UnitType.Value) = {
    outputType match {
      case UnitType.cel => x: Double => x * 1.8 + 32
      case UnitType.fah => x: Double => x * 1.8 + 32
    }
  }

  println(convert(32.0, UnitType.cel, UnitType.fah))

}

我会做以下事情:

  • 单位枚举。
  • 每个单元都有一个toKelvin and from Kelvin method.
  • 然后从单位换算a到单位b只是:b.fromKelvin(a.toKelvin())
  • 添加新单元只需要在新单元上实现这两种方法。

事实证明,在 Scala 中向枚举添加方法比在 Java 中更棘手,因此这里有一个使用单例实现特征的实现:

trait TemperatureUnit {
  def toKelvin(value : Double): Double
  def fromKelvin(value : Double): Double
  def convert(value : Double, unit : TemperatureUnit) : Double = fromKelvin(unit.toKelvin(value))
}

object Kelvin extends TemperatureUnit {
  def toKelvin(value : Double) = value
  def fromKelvin(value : Double) = value
}

object Celsius extends TemperatureUnit {
  def toKelvin(value : Double) = value + 273.5
  def fromKelvin(value : Double) = value - 273.5
}

然后将开尔文转换为摄氏度只需:

scala> Celsius.convert(100,Kelvin)
res0: Double = -173.5

您可能还应该添加一个包装类,这样您就不会裸露地传递Doubles(可能会意外地用作长度、时间戳等,而不会出现编译器警告)。

class Temperature (value: Double, unit: TemperatureUnit) {
  def to(new_unit: TemperatureUnit) = new Temperature(new_unit.convert(value,unit),new_unit)
}

然后当你写的时候

new Temperature(10,Celsius).to(Kelvin)

没有任何歧义了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实施策略模式的函数式方法 的相关文章

随机推荐

  • 如何从脚本向 sudo 提供密码?

    请注意 这是在我的本地计算机上运行的来宾虚拟机 VBox 我不担心安全性 我正在编写一个将在 Linux Ubuntu VM 上执行的脚本myuser用户 该脚本将在下面创建一个非常大的目录树 etc myapp 目前我必须手动完成所有这些
  • Telegram编译过程:没有规则来制作目标'/usr/lib/libicutu.a'

    我正在关注 Telegram 的编译过程here https github com telegramdesktop tdesktop blob master doc building cmake md在最后一步编译应用程序本身时 它给了我这
  • 谷歌放置片段上的Java空指针异常

    当我尝试尝试自动完成位置功能时 出现空指针异常 我像文档中一样添加了片段 并需要帮助来解决这个问题 谢谢 主要活动 package com example srinivas mapautocompletetest1 import andro
  • grunt:如何生成 HTML 形式的 jshint 输出

    我正在尝试使用 grunt 运行 jshint 这可行 但现在我希望输出为 HTML 这是我的 grunt 文件 module exports function grunt Project configuration grunt initC
  • 如何使用托管标识为逻辑应用程序创建与 Azure KeyVault 的 Api 连接

    Scenario 你好 我想创建Logic App从中得到秘密Azure KeyVault并将经过身份验证的请求发送到 API 并使用保管库中的秘密 Problem 我收到 The workflow connection parameter
  • JavaScript - 离焦事件?

    我想要做的是显示带有文本颜色的输入字段black 然后 当该人在输入字段内单击时 onfocus 我想将文本颜色更改为red 然后 当该人单击输入字段外部 不再焦点 时 我想将文本颜色更改回black 我知道如何处理 JavaScripto
  • jQuery ajax 调用在 Mac Safari 和 Chrome 浏览器上返回空错误

    我几天来一直在寻找解决方案并尝试修复 但没有任何改变 老板使用的是 Mac 而我没有 所以我让他尝试重复修复并将输出转发给我 到目前为止还没有运气 因此 当前的设置是 我有一个包含用户名和密码输入的表单 该表单在经过验证后提交 验证是一个
  • 一旦玩家与矩形对象发生碰撞,如何从屏幕上删除它?

    in draw 函数 我试图在玩家 pos 敌人 pos 时删除矩形对象 但 del 不起作用 有什么办法可以彻底删除敌人的物体吗 是否有内置的 pygame 函数可以删除我不知道的对象 draw player def draw enemy
  • Python从更高级别的包导入模块

    这是我的包层次结构 app init py Empty file server py global vars py handlers init py Empty file url1 init py Empty file app1 py ap
  • 在 C# 中实现记忆化 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我知道这个话题 记忆 已经被讨论了很多 比如here https stackoverflow com questions 285216
  • Python:定义多个相同类型的变量?

    可能是重复的 但至少我无法通过搜索这些术语找到答案 在Python中有没有更快的方法来做到这一点 level1 level2 level3 我试过了 level1 level2 level3 但这似乎创建了该对象的副本 这不是我想要的 和
  • CSS:最后一个子元素的高度应基于前一个兄弟元素,但不能溢出父元素

    相关 JS Fiddlehttp jsfiddle net arosen FMQtR http jsfiddle net arosen FMQtR Problem 我的 HTML 看起来像这样 div div A variable amou
  • 黄瓜和 Rspec

    任何人都可以向我推荐黄瓜和 rspec 教程 rails 3 的好来源 简单示例 吗 Edit 实际上我正在寻找带有很好示例的免费在线资源 我觉得R规格书 http www pragprog com titles achbd the rsp
  • 从纪元到相对日期的秒数

    我正在处理自纪元以来的日期 并且已经得到了 例如 date 6928727 56235 我想将其转换为另一种相对格式 以便我能够将其转换为与纪元相关的格式 使用 time gmtime date 它返回 year 1970 mon 3 da
  • 如何从PathName获取Project Guid和Model Guid?

    我的 Revit 模型有一个 RVT 链接 路径名称 BIM 360 BIM360 ArchitectureBIM360 rvt 中的测试链接编辑 我想构建一个 ModelPath 并使用它来打开云托管文件 如下所示 ModelPath m
  • 类方法的自定义代码完成?

    在 MATLAB 中 可以定义代码建议和完成 如标题为 的文档页面中所述 自定义代码建议和完成 https www mathworks com help matlab matlab prog customize code suggestio
  • 如何从 Ant 构建文件设置 Eclipse 构建路径和类路径?

    关于 Ant 和 Eclipse 有很多讨论 但之前的答案似乎对我没有帮助 事情是这样的 我正在尝试构建一个可以从命令行使用 Ant 成功编译的 Java 程序 更令人困惑的是 我尝试编译的程序是 Ant 本身 我真正想做的是将这个项目引入
  • Android Studio 不允许我更改 SDK 位置

    我打开 Android Studio 然后我打开 SDK 管理器 我拥有最新版本 但是我的 SDK 平台需要 Android 6 0 它甚至不让我点击任何东西 在此图像中 您可以看到文本和复选框变色 我无法单击 SDK 平台内的任何内容 甚
  • 压缩 Log4j 文件

    是否可以压缩日志文件 我通过 RollingFileAppender 进行 log4j 附加功能 http logging apache org log4j extras 对此表示支持 只需将以下内容添加到您的RollingFileAppe
  • 实施策略模式的函数式方法

    我正在尝试解决一个处理从一种温度单位到另一种温度单位 摄氏度 开尔文 华氏度 转换的问题 在Java中 我需要创建一个接口并提供多个实现来封装输入类型并将结果作为输出类型的单元返回 例如开尔文到摄氏度或摄氏度到华氏度等 我已经在 scala