Java Design Frage

samosa

Mitglied
Ich habe ein Design Problem.

Angenommen ich möchte Funktionen über mehrere Werte x1, x2, ..., xn ausrechnen. Zum Beispiel gibt es eine Funktion Mittelwert f1, eine Funktion Median f2, usw. Ich möchte dabei von Problem zu Problem entscheiden, welche Funktionen ich ausrechne.


Dazu nehme ich ein Interface

Java:
public interface Function {

    // records the next value
    public void update(double x);

    // returns the function value
    public double apply();
}

Die Mittelwert-Funktion kann dann so aussehen:
Java:
public class f1 implements Function { // Mean

    private double mean;
    private int n;

    public void update(double x) {
        mean = n*mean/(n+1) + x/(n+1);
        n++;
    }

    public double apply() {
        return mean;
    }
}

Nun gibt es Funktionen die auf anderen Berechnungen beruhen, zum Beispiel ist f3 der Mittelwert von der Folge z1 = sin(x1) + cos(x2), ...., zn = sin(xn) + cos(xn) und f4 ist der Median von z1, ..., zn.

Ich möchte, dass f3 und f4 das Interface Function implementieren. Wenn ich sowohl f3 als auch f4 benötige, möchte ich jedoch sin+cos nur einmal für jeden Wert x1, ...xn berechnen. Zum Beispiel möchte ich die Werte

mean = f1(x1, ...., xn),
median = f2(x1, ...., xn),
sin+cos mean = f3(x1, ...., xn),
sin+cos median = f4(x1, ...., xn)

nach erscheinen jedes neuen Wertes xi auf der Konsole ausgeben lassen und dabei nur einmal sin+cos für jedes xi berechnen.

Hinweis: Das Problem ist aufbereitet. Das eigentliche Problem ist etwas komplexer und vor allem habe ich statt sin+cos wesentlich komplexere Berechnungen, die man nur einmal ausführen sollte.
 
Zuletzt bearbeitet:
Fällt mir gerade auch etwas schwer das Nachzuvollziehen.
Aber im Allgemeinen kannst du LookUp-Tabellen verwenden für komplizierte Berechnungen, vor allem wenn die Werte in einem bestimmten Intervall liegen.
 
Die Frage ist, wie können f3 und f4 das Interface Function implementieren, so dass eine komplexe Berechnung (hier im Beispiel sim+cos) bei f3.update(x) und f4.update(x) nur einmal ausgeführt wird?
 
Moin,

Die Frage ist, wie können f3 und f4 das Interface Function implementieren, so dass eine komplexe Berechnung (hier im Beispiel sim+cos) bei f3.update(x) und f4.update(x) nur einmal ausgeführt wird?
Java:
implements Function
???:L
Verstehe Deine Frage irgendwie nicht ....

BTW: Du solltest Deine Funktionen NICHT f1 ... f4 nennen. Glaube mir, in ein paar Wochen weißt Du selbst nicht mehr, was was bedeutet! ==> nimm 'sprechende' Bezeichner !!

Gruß
Klaus
 
Hi Klaus,

wie im ersten Post bereits bemerkt, die Darstellung des Problems ist eine Vereinfachung des tatsächlichen Problems. Deswegen habe ich mir die Freiheit genommen, entgegen der üblichen Konventionen kurze Namen wie f1, f2 usw. zu wählen.

Wenn f3 und f4 das Interface Function implementieren, dann ruft man regelmäßig

f3.update(x_i)
f4.update(x_i)

auf und gibt das Ergebnis auf der Konsole aus. In diesem Fall würden sin(x_i) + cos(x_i) zwei-mal berechnet werden. Das ist in diesem Beispiel nicht so schlimm, wirkt sich aber auf die Laufzeit aus, wenn statt sin+cos komplexere Berechnungen durchgeführt werden. Was kann ich machen, dass ich diese Berechnungen, also hier sin+cos nur einmal aufrufe?
 
Zuletzt bearbeitet:
Eigentlich gar nichts. Ich wüßte keine Lösung ausser eben alle Berechnungen auf einmal in einer Klasse zu machen. Da kannst du deine lokalen Variablen weiter verwenden.

Ansonsten halt irgendwas fürchterliches zusammen basteln was aber kein Mensch später mehr nachvollziehen kann. Sowas, das die eine Methode eben nicht nur das Ergebnis zurück gibt sondern eine eigene Klasse in der das Ergebnis und einige Zwischenschritte (wie eben das addieren von sin und cos) enthalten sind und dieses Ergebnis kannst du dann an eine weitere Methode übergeben die sich die Zwischenergebnisse dort wieder heraus holt. Aber wie gesagt, das wäre ein fürchterliches Antipattern.

Gruß

Claus
 
Erst einmal Danke für Eure Zeit.

Einen Vorschlag, den ich habe ist folgender: Ich habe eine Klasse für die komplexen Berechnungen:

Java:
public class WorkHard {

    public double sincos(x) {
        return sin(x) + cos(x);
    }
}


Ich baue mir dann eine Liste von Funktionen:

Java:
public class Funs extends List<Functions> {

    WorkHard wh;
    boolean workHardIsRequired;

    public void add(Function f) {
        super.add(f);
        if(needsWorkHard(f) && ! workHardIsRequired) {
            wh = new WorkHard();
            workHardIsRequired = true;
        }
    }

    public void update(double x) {
        if(workHardIsRequired) {
            double y = wh.sincos(x);
        }
        for(Function f : this) {
            if(needsWorkHard(f)) {
                f.update(y);
            } else {
                f.update(x);
            }
        }
    }
}

Wenn ich meine Funktionen aufrufen möchte, füge ich sie der Liste hinzu. Funktionen, die Daten von WorkHard benötigen, erhalten eine Art Markierung, zum Beispiel implementieren sie ein MarkerInterface
Code:
WorkHardFunction implements Function
. Über instanceof könnte die Methode
Code:
needsWorkHard(f)
abfragen, ob Funktion f die Daten von WorkHard benötigt.

Das sieht alles sehr hässlich aus, oder? Was meint Ihr?
 
OOP eignet sich halt nicht für alle Arten von Problemlösungen. Dazu gehört definitiv komplexe mathematische Lösungen abzubilden. Gerade wenn es um Rechen-Performance geht ist OOP sehr oft der falsche Weg und man sollte lieber prozduale Lösungen suchen.

Gruß

Claus
 
Hallo Klaus,

also alle Berechnungen in einer Klasse?

Ich habe allerdings das Problem, dass von etwa 20 Funktionen meist ein bis fünf Funktionen ausgewählt werden, die dann kontinuierlich angezeigt werden. Ist da der prozedurale Ansatz nicht ebenso unübersichtlich?

Gruß

s
 
Schwer zu sagen ohne das ganze Konzept zu kennen. Eventuell gibt es ja noch einen komplett anderen besseren Ansatz. Aber dazu müßte ich ja erstmal das große Ganze verstehen 🙂

Gruß

Claus
 

Zurück
Oben