Devo usare una classe che chiama diversi metodi statici o più classi, ognuna delle quali chiama un metodo statico

0

Ho bisogno di usare le istanze che rappresentano le funzioni matematiche insieme ai loro parametri per consentire la loro valutazione. Posso prendere 2 approcci:

1: ha una singola classe che rappresenta tutte le funzioni matematiche:

class TrigonometricFunction extends Function {

    private double param;

    private String name;

    public TrigonometricFunction(double param, String name) {
        this.param = param;
        this.name = name;
    }

    public double evaluate() {

        double radParam = toRadians(param);

        if ("sin".equals(name)) {
            return Math.sin(radParam);
        }

        if ("cos".equals(name)) {
            return Math.sin(radParam);
        }

        // about 10 more functions would go here...

    }
}

Vantaggi di questo approccio:

  • devono creare e testare solo una singola classe
  • nessuna duplicazione del codice (conversione di parametri in radianti)

Svantaggi:

  • valutazione inefficiente (devi fare molti confronti tra stringhe in evaluate () a seconda del nome della funzione), ma sarebbe anche un problema?
  • sembra brutto e non sembra giusto

2: avere una classe separata per ogni funzione matematica:

class SinFunction extends Function {

    private double param;

    public SinFunction(double param) {
        this.param = param;
    }

    public double evaluate() {

        double radParam = toRadians(param);

        return Math.sin(radParam);
    }
}

class CosFunction extends Function {

    private double param;

    public CosFunction(double param) {
        this.param = param;
    }

    public double evaluate() {

        double radParam = toRadians(param);

        return Math.cos(radParam);
    }
}

I vantaggi:

  • le piccole classi, una singola responsabilità, sembrano solo migliori
  • valutazione più efficace come nella prima soluzione (senza confronti tra stringhe) (?)

Svantaggi:

  • devono implementare e testare un sacco di piccole classi che sembrano fondamentalmente le stesse
  • codice duplicato (chiamando la conversione in radianti in ogni classe)
  • più costoso per creare istanze (devi fare il confronto String qui).

Quale approccio è migliore e perché? O hai una soluzione migliore?

    
posta Jardo 19.01.2015 - 21:09
fonte

1 risposta

5

Suppongo che l'input che il tuo codice riceve sia comunque la rappresentazione in stringa della funzione, quindi non è possibile evitare il controllo delle stringhe. Vi sono, tuttavia, modi per evitare alcuni degli altri problemi che hai notato.

Vorrei andare con la tua opzione n. 2, con i seguenti avvertimenti:

Il codice condiviso deve essere condiviso

Piuttosto che estendere Function , crea una classe di base intermedia chiamata TrigonometricFunction che comprende il codice condiviso, in particolare la conversione in radianti:

public abstract class TrigonometricFunction extends Function {

    protected double radians;
    protected TrigonometricFunction(double paramDegrees) {
        radians = toRadians(paramDegrees);
    }

    abstract double evaluate();    
}

E estendilo per funzioni specifiche.

public class SinFunction extends TrigonometricFunction {    
    @Override
    public double evaluate () {
        return Math.sin(radians);
    }
}

In questo modo mantieni la sicurezza del testo e riutilizzi anche il codice.

Utilizza un modello dispatcher / factory per evitare if / else string checks

Invece di fare if (name == "sin") { return new SinFunction(params); } , puoi usare un oggetto Factory per creare l'oggetto Function pertinente e scegliere il Factory rilevante usando una Hashmap con il nome della funzione:

public interface TrigonometricFunctionFactory {
    TrigonometricFunction buildFunction(double paramDegrees);
}

public SinFunctionFactory implements TrigonometricFunctionFactory {

    @Override
    public TrigonometricFunction buildFunction(double paramDegrees) {
        return new SinFunction(paramDegrees);
    }
}

e così via per altre funzioni. Ora crea questa tabella di spedizione:

HashMap<string, TrigonometricFunctionFactory> dispatchTable = new HashMap<>();
dispatchTable.add("sin", new SinFunctionFactory()); 
dispatchTable.add("cos", new CosFunctionFactory());

e ora puoi fare questo:

String functionName = "sin";
result = dispatchTable[functionName].createFactory(param).evaluate();
    
risposta data 19.01.2015 - 21:35
fonte

Leggi altre domande sui tag