数学公式设计模式

时间:2013-07-03 05:50:14

标签: c# java objective-c

例如,我需要一个计算牛顿定律F = MA的函数,所以我在C#中编写以下代码

private double calcForce(double mass, double acceleration){
        return mass * acceleration;
}

private double calcMass(double force, double acceleration){
        return force / acceleration;
}

private double calcAcceleration(double force, double mass){
        return force / mass;
}

如果数学函数具有少量变量(F = MA只有3个),并且功能更复杂(我的真正任务是处理传热/流体力学函数,它很容易包含10个以上变量! )方法的数量将等于该数学函数中的变量数。

那么,有没有好的设计模式可以解决这个问题。我应该使用这样的东西吗?

private double NewtonsLaw(double? force,double? mass,double? acceleration)
{
        if(!force.HasValue)
            return mass*acceleration;
        //else if
}

还有一件事,我需要在objective-c和java中编写代码而不是C#。

3 个答案:

答案 0 :(得分:0)

一种方法是使用质量/加速度/力值创建一个对象(取决于设置的值)计算它们或只返回它们

public class NewtonLaw {
    private Double mass;
    private Double acceleration;
    private Double force;

    public NewtonLaw(Double mass, Double acceleration, Double force) {
        this.mass = mass;
        this.acceleration = acceleration;
        this.force = force;
    }

    public Double calcMass() {
        if (mass != null) {
            return mass;
        } else if (acceleration == null) {
            throw new IllegalStateException("Acceleration is not set");
        } else if (acceleration == 0) {
            throw new IllegalStateException("Acceleration is zero, cannot calculate the mass");
        } else if (force == null) {
            throw new IllegalStateException("Force is not set");
        } else {
            return force / acceleration;
        }
    }

    public Double calcAcceleration() {
        if (acceleration != null) {
            return acceleration;
        } else ...
    }

    public Double calcForce() {
        if (force != null) {
            return force;
        } else ...
    }
}

不可否认,这只是一些代码,仅用于少量计算,但至少逻辑完全封装在对象中

答案 1 :(得分:0)

我认为最好为每个可能的组合使用单独的方法,而不是让用户传递可空类型,并将一个值设置为null。

如果你提供一个私有构造函数,它接受所有值和一组公共静态工厂方法,每个方法都接受除一个值之外的所有值,它将使代码在调用时更清晰,并且它也意味着您不需要检查除了其中一个值之外的所有值都是非空的。

像这样(用C#编写,但概念很容易转换为Java或Objective C):

public class Newton
{
    readonly double _force;
    readonly double _mass;
    readonly double _accel;

    public double Force
    {
        get { return _force; }
    }

    public double Mass
    {
        get { return _mass; }
    }

    public double Accel
    {
        get { return _accel; }
    }

    public static Newton FromForceAndMass(double force, double mass)
    {
        return new Newton(force, mass, calcAccel(force, mass));
    }

    public static Newton FromForceAndAccel(double force, double accel)
    {
        return new Newton(force, calcMass(force, accel), accel);
    }

    public static Newton FromMassAndAccel(double mass, double accel)
    {
        return new Newton(calcForce(mass, accel), mass, accel);
    }

    private static double calcAccel(double force, double mass)
    {
         return force / mass;
    }

    private static double calcForce(double mass, double acceleration)
    {
        return mass * acceleration;
    }

    private static double calcMass(double force, double acceleration)
    {
        return force / acceleration;
    }

    private Newton(double force, double mass, double accel)
    {
        _force = force;
        _mass  = mass;
        _accel = accel;
    }
}

(不检查值除以零 - 您必须为此添加错误检查。)

然后你在哪里调用它,发生的事情更加明显:

var newton = Newton.FromForceAndAccel(1.234, 6423.2);

这对单独方法的数量没有帮助,但它有一个很好的使用模式。

答案 2 :(得分:0)

无论您使用何种模式,您都必须对新值的计算进行编码。所以它意味着至少有10种传热/流体力学问题的公式。

将所有这些放在带有可选参数的相同方法中是一个坏主意,因为它会使您的代码更复杂(因此更多的bug,更难维护等)。另外,你可能在你的论证顺序上错了,然后计算一些不同的东西(你想要计算质量,但是你在计算加速度)。

最好将这10个公式封装在不同的方法中。它将更容易实现任何错误检查/处理,更容易调试,测试和维护。

现在,您可以将这10个方法封装在一个对象中,以便为您提供方便您自己使用的界面。以前的评论包含好主意。选择一个适合你的。