繁体   English   中英

是否有一个预先存在的类来定义Java中对数字的一系列运算?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM