我怎么可能在Java中实现单位转换器?我在想一个抽象的基类:
public abstract class Unit {
...
public void convertTo(Unit unit);
}
然后让每个类如Meter
Kilometer
Inch
Centimeter
Millimeter
...派生自该基本单元类。所有长度单位都在一个名为com.unitconverter.distance的包中,然后是一个包,com.unitconverter.energy,用于能量等等。那么这是实现单位转换器的最佳方法吗?或者有更好或更简单的方法吗?
答案 0 :(得分:12)
对此有相当多的工作,包括JSR 108(撤回)和JSR-275(拒绝)。请参阅后者的JScience和UnitsOfMeasure实施
答案 1 :(得分:4)
您应该检查 java.util.concurrent.TimeUnit 的实现方式,作为参考。这是一个支持convert(..)操作的枚举。
答案 2 :(得分:2)
要实施Unit
转换器,您要从一个Unit
转换为另一个convertTo()
。所以我会有一个名为Unit
的方法,它会占用一个Unit
对象并返回另一个Unit
对象。
Unit
类的每个子类都有自己的定义,用于将自身转换为某个中介Unit
,以及它如何将值从某个中间Unit
转换为自己的convertTo()
{ {1}}。
要转换它,您的Unit
方法会调用自己的方法将自身转换为替代Unit
,然后调用另一种方法将该中间转换为convertFrom()
类型作为参数传递的那个(因为传递的那个有自己的{{1}}方法)。
答案 3 :(得分:1)
不要忘记,虽然您需要对单元概念进行建模,但它实际上是您要转换的“单位+数量”。此外,维度的概念很重要,因为它限制了哪些转换是有意义的(即米到码都是长度;摄氏到瓦特不是)。
答案 4 :(得分:1)
作为转换器,单位是数据,并不真正属于代码。
你可以做一些非常棒的东西,但是,如果你将你的单位分解为“基础”组件(长度,温度,时间......)
所以你可能有一个如下所示的数据库:
分钟= 1 x时间(其中时间是时间的基本测量单位)
秒=时间/ 60
小时=时间* 60
米= 1 x距离
Klometer = 1000 x距离
...
关于这一点的好处是你开始用公式获得真正的灵活性。例如,如果我有一些信息,就像我正在观看的蜗牛在3分钟内移动了20厘米,我可以轻松地将其提供给速度方程(速度= dist / time)以获得“Root”速度数字,然后根据不同的单位(比如英里和小时)请求结果,这样我就可以立即获得每小时英里数的结果。
你甚至知道你缺少什么信息 - 比如如果你给出距离并要求速度,它可以回应“你还需要时间”。或者,如果你给出一个距离和速度,它可以按你选择的单位计算一个时间。
无论如何,这都是数据。你可能甚至不应该有不同的距离和时间类。
我想我会使用一组固定的测量对象,如上所述可以用来查找转换(单位名称,单位类型,转换因子),如(“Minutes”,TIME,1)
当用户输入带有单位的值时(假设用户输入3小时),我只需查看单位(“小时”),找出转换(180,时间)和存储(180,TIME)某处。
当他们在几分钟内要求读数时,我会查找转换分钟(“分钟”,TIME,1)并使用缩放系数(1)确定您需要打印180分钟。
如果用户输入的值为3小时并要求以米/秒为单位的速度,则可以提示输入距离(用户可以使用任何距离类型指定)并轻松转换为所需的输出。转换为基本单位并使用缩放因子几乎可以消除所有困难。
理由/推理:
我断言不应该在代码中指定单位和转换因子可能会受到质疑......
我的理由是你永远不应该拥有没有UNIQUE业务逻辑的对象。
分钟和秒之间的唯一差异将是一个公式,它只会在常数中变化(使用任何分钟,你也可以使用秒x 60或小时*(1/60),这样常数(1, 60,1 / 60)不能导致自己创建一个新类 - 这绝对是犯罪。
所有基本测量类型都是如此,它们都没有独特的业务逻辑。
答案 5 :(得分:0)
当您希望实现某些默认行为时,以及您希望确保实现某些非默认行为的某些方法时,使用抽象类是很好的。如果您只想确保实现Unit
个继承者的单个方法,则应使用接口。
答案 6 :(得分:0)
您可以使用稀疏图实现单位转换。如果两个单元之间存在转换,则在两个单元之间创建边。传递闭包中的Ergotic集是同一物种的单位(长度,时间等)。