我正在尝试解决一个处理从一种温度单位到另一种温度单位(摄氏度、开尔文、华氏度)转换的问题。
在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
您可能还应该添加一个包装类,这样您就不会裸露地传递Double
s(可能会意外地用作长度、时间戳等,而不会出现编译器警告)。
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(使用前将#替换为@)