[英]Is there a pre-existing class to define a sequence of operations on numbers in Java?
我正在用Java开发图形用户界面,并依赖于标准MVC设计模式,在该模式中,我具有一个View,该View应该提供模型状态的最新表示。
我在View中有一个ObserverTextField
类,该类JTextField
并将其注册为模型一部分的观察者。 当模型的这一部分更改时,它将调用此观察者的notify
方法,并传递整数值。 然后,该类将其显示的文本设置给用户。
但是,我希望能够在运行时控制数字的表示。 我可以将NumberFormat
传递给该类,但这似乎无法将值表示为实际值的1/1000。
例如,如果模型以毫安为单位存储电流值,并且我希望以安培为单位向用户显示该电流,那么是否可以构造某种对象并将其传递给ObserverTextField
来让它做到这一点?
以下是使用NumberFormat
实例的代码示例,我想将其替换为更强大的功能:
public class ObserverTextField extends JTextField implements Observer {
private static final long serialVersionUID = 1L;
private NumberFormat formatter;
@Override
public void notify(Object value) {
if(formatter == null) {
setText(String.valueOf(value));
} else {
setText(formatter.format((int)value));
}
}
public NumberFormat getFormat() {
return formatter;
}
public void setFormat(NumberFormat formatter) {
this.formatter = formatter;
}
}
如果没有这样的东西,我可以创建自己的东西,但我更希望首先确保Java标准库中不存在类似的东西。
您的观察者可以具有一个实用程序函数,该函数将格式化您的值,如下所示:
private static DecimalFormat df = new DecimalFormat("#.000");
public static String getFormattedValue(double value, double factor) {
return df.format(value * factor);
}
这是main
的例子
public static void main(String[] args) throws Exception {
double value = 3560;
System.out.println(value + " milliamps");
//Milliamps to centiamps is a factor of .1
System.out.println(getFormattedValue(value, .1) + " centiamps");
//Milliamps to deciamps is a facotr of .01
System.out.println(getFormattedValue(value, .01) + " deciamps");
//Milliamps to amps is a factor of .001
System.out.println(getFormattedValue(value, .001) + " amps");
}
输出:
3560.0 milliamps
356.000 centiamps
35.600 deciamps
3.560 amps
Java 8承诺提供一个不错的解决方案:
textField.setFormat((n) -> (n.intValue() / 1000) + " mA");
private Function<Number, String> formatter = (n) -> n + " A";
@Override
public void notify(Object value) {
setText(formatter.apply((Number)value));
}
public void setFormat(Function<Number, String> formatter) {
this.formatter = formatter;
}
从答案来看,Java中似乎没有内置的方法可以对数字执行任意转换,因此我整理了一个简单但可用的自定义实现。 我创建了一个实用程序类MathSequence
:
import java.util.LinkedList;
import java.util.List;
public class MathSequence {
private interface MathOperation {
double operate(double value);
}
private class AddOperation implements MathOperation {
private double operand;
public AddOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value + operand;
}
}
private class SubtractOperation implements MathOperation {
private double operand;
public SubtractOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value - operand;
}
}
private class MultiplyOperation implements MathOperation {
private double operand;
public MultiplyOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value * operand;
}
}
private class DivideOperation implements MathOperation {
private double operand;
public DivideOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value / operand;
}
}
private List<MathOperation> operations;
public MathSequence() {
operations = new LinkedList<MathOperation>();
}
public void appendAddOperation(double operand) {
operations.add(new AddOperation(operand));
}
public void appendSubtractOperation(double operand) {
operations.add(new SubtractOperation(operand));
}
public void appendMultiplyOperation(double operand) {
operations.add(new MultiplyOperation(operand));
}
public void appendDivideOperation(double operand) {
operations.add(new DivideOperation(operand));
}
public void clearOperations() {
operations.clear();
}
public double process(double value) {
for(MathOperation operation : operations) {
value = operation.operate(value);
}
return value;
}
}
然后,我更改了ObserverTextField
类:
public class ObserverTextField extends JTextField implements Observer {
private static final long serialVersionUID = 1L;
private NumberFormat formatter;
private MathSequence sequence;
public ObserverTextField() {
formatter = new DecimalFormat("");
sequence = new MathSequence();
}
@Override
public void notify(Object value) {
int integerValue = (int)value;
setText(formatter.format(sequence.process(integerValue)));
}
public NumberFormat getFormat() {
return formatter;
}
public void setFormat(NumberFormat formatter) {
this.formatter = formatter;
}
public MathSequence getSequence() {
return sequence;
}
public void setSequence(MathSequence sequence) {
this.sequence = sequence;
}
}
然后,我可以编写如下代码:
MathSequence sequence = new MathSequence();
sequence.appendDivideOperation(1000);
NumberFormat formatter = new DecimalFormat("0.000");
ObserverTextField actuatorCurrentTextField;
actuatorCurrentTextField = new ObserverTextField();
actuatorCurrentTextField.setSequence(sequence);
actuatorCurrentTextField.setFormat(formatter);
这将显示我喜欢的表示形式。 由于这种方法,我不会在ObserverTextField
类本身中对值的表示形式进行硬编码,因此我可以在运行时自由更改表示形式,并轻松地重用代码。 这就是为什么我不能接受“为什么不做(int)value / 1000?”这样的建议的原因。
我会接受其他答案之一,尽管我暂时可能会坚持使用这个答案,因为它们非常有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.