Optionen-Klasse: Welches Pattern?

Welches Pattern sollte man nutzen, um Optionen in ein Programm zu integrieren? Ich mache es immer so, dass ich die Variablen nutzen und verändern möchte, sowie auch gleich einen Lade- und Speicheralgo integriere.

Zunächst zum Zugriff auf die Klasse selber:

  1. Einfach alles static, dann kann der Zugrifff leicht erfolgen (aber alle scheinen static zu meiden, also sollte es andere Varianten geben)
  2. Singleton (aber JEDER hier HASST sie [was ich nicht verstehe, aber egal])
  3. “Normale” Klasse mit Konstruktor und allem drum und dran (aber dann müsste die Instanz an JEDE andere Klasse weitergegeben werden, was denke ich nicht im Sinne von OOP ist)

Nun der Zugriff auf die Variablen:

  1. Static (siehe oben)
  2. Getter/Setter
  3. public (aber sie sollen ja so wenig wie möglich sichtbar sein)

Zuletzt der Zugriff auf den Lade- und Speicheralgo:

  1. Static YEAH
  2. normale Methoden
  3. den Ladealgo in den static{}-Block, Speichern als Methode

Wie würdet ihr vorgehen? Was haltet ihr von meinen Ansätzen, oder kann man sie direkt in die Tonne kloppen? Was ist hier ein guter Programmierstil? Gibt es dafür irgendwelche Standartpattern?

Danke schon im Voraus für eure Antworten!

mfg
BH16

  1. Du solltest dir mal das Konzept und den Hintergrund von Dependency Injection anlesen, dann wirst du merken, dass deine Singletonitis mehr eine Krankheit ist, als saubere Programmierung.
  2. Ich würde für die Strukturierung der Optionen Klassen das Composite Pattern anwenden. Das ermöglicht z.B. Unteroptionen, also Baumstrukturen.
  3. Warum machst du deine Variablen Public und bietest noch Setter/Getter an? Das ist schon fast nicht mehr witzig.

Mit dem “static” verändert sich der “Flow”.

Die Klasse die die Variable verwendet muß Sie sich holen und ist darauf angewiesen, dass dort ein korrekter Wert vorhanden ist.

Um nun zu Testen ob die Klasse vernünftig arbeitet, benötigt man immer auch die andere Klasse, die den Wert der Variable vorhält.

Auf den ersten Blick scheint das keinen großen Unterschied zu machen, aber er tut es.

class HelloWorld {
  private final String greeter;
  public HelloWorld(String greeter) {
    this.greeter = greeter;
  }

  public String greet(String name) {
    return greeter + " " + name;
  }
}```

Das kann man testen mit

```assert new HelloWorld("Hello").greet("World").equals("Hello World");
assert new HelloWorld("Hallo").greet("Welt").equals("Hallo Welt");```

class HelloWorld {
public String greet(String name) {
return Greeter.greeter + " " + name;
}
}

class Greeter {
public static final String greeter = “Hello”;
}


Jetzt sieht das HelloWorld zwar etwas kürzer aus, aber ich hab mir eine Abhängigkeit an die Greeter Klasse ans Bein gebunden.

zu 1. Ich werde mich vllt demnächst mal dazu belesen.
zu 2. Das scheint interessant zu werden, vllt durchdringe ich dann endlich mal die richtige OOP (damit hab ich teilweise noch Probleme, besonders bei der Vererbung) :slight_smile:
zu 3. jedes der o.g. Punkte ist eine einzelne Idee. Ich würde niemals auf die Idee kommen eine public static Variable mit Getter zu machen o.O Denn das ist echt fast schon peinlich :wink:

mfg
BH16

Ich glaube gelegentlich einen starken Kontrast zu beobachten, zwischen

  • wie spezifisch/genau die Frage ist und
  • wie spezifisch/genau die Antwort ist

Was sind denn “Optionen”? Wer braucht die? Und wofür? Und WIE werden sie verwendet? (Zur Laufzeit gändert usw…?)

Optionen sind in meinem Falle alles, was man einstellen kann. Bei einem Spiel wären das z.B. AA, Bufferung etc. Bei einer Simulation die Standartwerte zur Initialisierung (z.B. Bufferung, Threadspeed, Größe der Simulation, Fenster-Bounds). Also an sich alles, was in irgend einer Art und Weise Eigenschaften von irgendetwas beeinflusst und gespeichert werden könnte. Und ja, insofern können sie auch während der Laufzeit geändert werden.

mfg
BH16

Das Laden und Speichern kann man auch mittels der Properties Klasse uebernehmen. Die besitzen schon laden/speichern als xml oder .properties. Nun kann man sich auch ueberlegen dass eigebtlich jede Klasse irgendwad speichern kann. Man koennte also die Felder die gespeichert werden sollen annotieren und dann am Ende fuer jedes feld als Schluessel den Namen nehmen und diese dann in einer Datei speichern die den Klassenbamen(vollen) entspricht. Beim laden eben setzt man den Wert des Feldes(man hat ja den Namen) und schon kann es losgehen :smiley:
Es ist vielleicht keine saibere Sache(meiner Meinung nach simpel zu schreiben und zu benutzen, aber jedem den seine…). Beim Beenden der JVM kann man dann einfach alle Klassen im Classpath durchauchen und ermitteln ob sie eine bestimmte Anno haben, falls ja werden die Felder geprueft, falls nicht dann eben nicht…

@Service
public class View {

@Save
private String username;

//... Bla bla bla...
}

Dann muss nur beim Start eben alles gescannt werden und gesetzt werden. Das sollte einfach sein,bman braucht nicht viel zu konfigurieren und es ist alles ‚unsichtbar‘ im Hintergrund. Klar es hat auch seine Nachteile, aber so kann man fuer seine POJO’s schnell Werte speichern…

Ja, Properties und ähnliches sind so eine Sache. Ich kenne mindestens ein großes Projekt, wo aller möglicher Sche!ß in einer Properties-Map gespeichert ist. Jeder schreibt irgendwo irgendwas mit magischen Strings als keys da rein, und jeder liest irgendwas mit magischen Strings als keys wieder aus. Das ganze wird natürlich (?) trotzdem gnadenlos vom Einlesen bis zum letzten Drecks-Button im GUI weitergeschleift. Demjenigen, der das verbrochen hat, hat das damals bestimmt viel Arbeit erspart.

Die angedeuteten Punkte klingen bisher so, als wären viele davon Read-Only - aber gerade wenn sie NICHT read-only sind, kann man IMHO leicht in Teufels Küche kommen, wenn jeder zu jedem Zeitpunkt Änderungen darin machen darf, ohne, dass jemand was davon mitbekommt. Als Sugestivbeispiel: Wenn zu diesem Spiel z.B. irgendwelche antiAliasing-Settings und zu der angedeuteten „Simulation“ sowas wie eine Zeitschrittgröße gehört, kann man natürlich sowas machen wie

public class Settings {
    private static boolean antiAlias; // + get/set
    private static double timeStep; // + get/set
}

Dann bleibt nur zu „„hoffen““, dass…

  • der Simulator sich den timeStep nicht einmal im Konstruktor holt und speichert, sondern immer schön über Settings.getTimeStep() „frisch“ holt, damit er Änderungen daran mitbekommt
  • das ganze nie im GUI angezeigt werden soll (bzw. nie von einer anderen Stelle als EINER GUI-Component geändert wird) weil sonst garantiert irgendein falscher Wert im GUI angezeigt wird
  • man sich wegen der Abhängigkeiten, die damit ALLE Klassen zu der EINEN Settings-Klasse bekommen, nicht irgendwann in den Hintern beißt
  • dass in dieser Klasse nicht Sachen vermischt werden, die rein thematisch nichts zu tun haben - wie etwa rendering-settings und simulations-settings… :wink:

Ich denke, dass man solche Einstellungen oft sinnvoll gruppieren und zusammenfassen könnte. Klassen wie „GraphicsSettings“ und „SimulationSettings“ wären zumindest eine Überlegung wert. Sicher müssen Instanzen davon an die jeweiligen Stellen weitergereicht werden, aber das sind ja speztische Informationen, die NUR an die Klassen übergeben werden müssen, die diese Informationen auch zwingend brauchen. Ich denke also schon, dass man da im Einzelfall Lösungen findet, die ohne statics und und mißbrauchte Singletons auskommen, und nebenbei auch Dinge erlauben, wie etwa, über Änderungen an diesen Werten informiert zu werden. Dass das auf den ersten Blick „aufwändiger“, „komplizierter“ oder gar „umständlicher“ wirkt, als alles in eine public static Map<String, String> settings zu packen, mag stimmen, aber beim Abwägen der potentiellen (aber schon „absehbaren“) Vor- und Nachteile sollte man die oben genannten wohl zumindest berücksichtigen…

Ich meinte ja nicht eine properties map fuer alles, sondern nur eine fuer jede Klasse die was zu speichern hat. Dann kann man die Sache einfach in eine directory schreiben und fertig.