Programmstruktur für "statische" Methoden

Auch das ist kein Singleton, sondern eine statische Methode (um mal den korrekten Java-Begriff zu verwenden) einer Methodensammlung. Diese hier, greift auf die einzige existierende statisch private Instanz der Klasse Math zu. Hindert keinen daran, Random selber zu instanzieren um es z.B. ebenso zu verwenden, wie die Klasse Math.

Uff erst einmal vielen Danke für die zahlreichen Informationen. Da muss ich jetzt erst mal durchsteigen.

Im gesetzten Kontext der Klasse, kann es aber vielleicht schon als Sigleton gelten! Oder anders: Die genaue Bezeichnung, wenn eine Klasse („bei Bedarf“) nur auf maximal eine Instanz einer andern Klasse greift (diese Klasse aber unabhängig davon „ganz normal“ verwendet werden kann/darf), kenne ich auch nicht.

Aber selbstverständlich habt ihr recht, Singleton ist dafür da, dass so etwas nur einmal passiert, und danach nie mehr.

Kann es nicht. Um das zu verstehen, müsste man aber die Definition Singleton kennen. Eine Klasse kann eine private Klasseninstanz einer Klasse statisch definieren, diese muss aber nicht vom Typ Singleton sein. Von einem Singleton gibt es programmweit nur eine einzige Instanz und das ist für Random alles andere als zutreffend, weil es von überall her instanziert werden kann.

So nachdem ich eure Beiträge alle durchgearbeitet und eine Nacht drüber geschlafen habe um es zu verinnerlichen, versuche ich hier mal weiter mein Anliegen in Richtung Ziel zu bewegen :wink:


Für die konkrete Instanzierung soll eine Init-Mehtode aus einer Klasse dienen, welche das Interface „ServletContextListener“ implementiert. Diese müsste und wird auch vor allem anderen ausgeführt, so das ich hier bequem meine Initalisierung durchführen kann. Welche Implementierung Verwendung finden soll, ist in einer Konfigurations-Datei definiert. So das ich mittels Reflection an die richtige Implementierung herran komme. An dieser Stelle muss ich mir aber auch eingestehen, das ich hier einen Denk- und Konzeptionsfehler habe. Denn theoretisch könnte man so im weiteren Programmverlauf abweichend zur initalisierten Implementierung „ausversehen“ auf jede andere Implementierung zugreifen, solange diese bekannt ist. Das ist ein Problem, welches ich aktuell so noch nicht bedacht habe.


Hier kann dich dir nicht genau folgen. Wie kann man statische Methoden in einem Interface verwenden?


Könnte bitte noch mal jemand, der das Gesamte überblickt zusammenfassen, welche Möglichkeiten ich habe und was für mein Vorhaben das beste wäre?

Vielen Dank an @all

Was spricht dagegen, die Klasse an alle Orte, wo sie verwendet wird, weiter zu reichen?

Alles in allem klingt dein Problem so, als würdest du an der falschen Stelle nach einer Lösung suchen. Reflections einzusetzen ist keine gute Idee, es sei denn, das ist absolut unumgänglich, und das scheint es mir bei deiner Problembeschreibung nicht zu sein. Kann aber auch gut sein, dass ich es nicht richtig verstanden habe.

Weitere Beträge tragen zur zunehmenden „Verwirrung“ und „Fragmentierung“ des Themas bei. Deine Frage ist doch eher „allgemein gehalten“, d. h. Entwurfsmuster und Designentscheidungen gibt es viele. Weitere, mehr konkretisierte SSCCEs wären nützlich und hilfreich - um eine konkrete Empfehlung nahezulegen.


Im Ernst und etwas Offtopic: Meine Glaskugel (Instinkt) ist gut (und wird langsam immer besser), aber an der Stelle kann selber ich nicht folgen. Vielleicht gab es in der Vergangenheit eine „krasse“ Fehl"design"entscheidung… Versuch macht klug/ Probieren geht über studieren, as far as i currently/actual know.

Dagegen spricht absolut nichts. Da bin ich allerdings etwas überfragt, wie das am besten gemacht wird. @Inject?


Die Reflection müsste ich nur verwenden, wenn ich dynamisch ein bestimmte Implementierung lagen würde.


Ja das ist sehr gut möglich. Das war eines meiner ersten großen Java-Programme und da war mein Kenntnissstand noch geringer als heute.

Da spricht nicht zwingend, aber doch potentiell etwas dagegen.

  1. Man „verschmutzt“ sich seine Interfaces

    interface Person {
       void setName(String name);
       void setAge(int age);
       ...
    }
    

    Ach Mist, in EINER Implementierung brauche ich die Funktionensammlung! Also…

    interface Person {
       void setName(String name, Funktionensammlung fuu);
       void setAge(int age, Funktionensammlung fuu);
       ...
    }
    

    Nicht gut… :dizzy_face:

  2. Damit verwandt: Ggf. weiß man (beim Design) ja noch gar nicht, wo man diese Funktionen brauchen wird. Pauschal bei jeder Methode einen Parameter hinzufügen (und damit auch eine dependency zu dieser Klasse) ist sicher kein gutes Design.

(So weit erstmal die Kritik. Die Lösung oder Verbesserung oder Vermeidung des ganzen? Schwierig. Aber vielleicht helfen diese Punkte ja, klarzumachen, dass man auch bei diesem (schwierigen) Problem genau über die Lösung nachdenkden sollte, und nicht das erstbeste machen, was „im Moment funktioniert“ :wink: )


EDIT: Ach ja: Eine „übliche“ (moderne) Lösung für dieses Problem, dass man eine Instanz braucht, aber nicht so genau weiß, welche das ist und wo sie herkommt, ist ja dependency injection. Leider kann ich da gerade nicht viel fundiertes dazu sagen, außer, dass mir die „Magie“, die da abläuft, auch immer etwas suspekt ist. Ansonsten wäre irgendwas @Inject-artiges ja vielleicht eine geeignete Lösung)

Wieso sollte man sowas machen? Bei einem Interface ist es doch völlig schnuppe, ob wie oder wann überhaupt eine Funktionssammlung verwendet wird. Der Implementierung gibt man dann einfach die Funktionensammlung mit. Entweder im Konstruktor oder man fragt jemanden wie man Function currying einsetzt.

Das die „Magie“ mit @Inject etwas suspekt ist, kann ich gut verstehen. Allerdings ist das Zeug mittlerweile relativ gut „abgehangen“ und in jeder Menge anderem Zeug enthalten. Da fielen dann JEE, JavaFX eigentlich schon komplett weg, wenn man das vermeiden wollte. Aber letztlich macht es nichts anderes als annotierte Member zu suchen und diese mit einer passenden Implementierung zu initialisieren oder für den Fall das es sich nicht für eine Implementierung entscheiden kann mit einer entsprechenden Fehlermeldung auszusteigen.


Warum ich das mit den Singletons und static Methods nicht so mag und hier Vorteile in DI sehe zeigt sich zum Beispiel in Eclipse RCP

https://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection

class MyView extends ViewPart {
  public void createPartControl(Composite parent) {
    Button button = ...;
    PlatformUI.getWorkbench().getHelpSystem().setHelp(button, "com.example.button.help.id");

    getViewSite().getActionBars().getStatusLineManager().setMessage("Configuring system...");
  }
}

Eclipse 3.x und im Unterschied mit Eclipse 4.x

  @Inject
  public void create(Composite parent, IWorkbenchHelpSystem help) {
    Button button = ...;
    help.setHelp(button, "com.example.button.help.id");
 
    slm.setMessage("Configuring system...");
  }
}

Das war das, was man (IMHO ohne viel bösen Willen :wink: ) in die Aussage mit dem „Weiterreichen“ von @Crian reininterpretiern könnte …

Dann sehe ich auch kein Problem damit. Aber halte statische Methoden dennoch für gefährlich. Unser legacy-code ist voll davon und das einzige was hilft das testbar zu bekommen sind wrapper-klassen oder PowerMockito (was aber die Tests langsam macht und wir deswegen davon weg sind).

Statische Methoden nehmen die wie angesprochen aber mehr als Delegation oder builder funktionieren.

Schlecht:

 public static int doMaths(int a, int b) {
    return (a+b)*a/(b-a);
}

Ok:

 public static int doMaths(int a, int b) {
    return myMathImpl.doMaths(a,b);
}

Singleton-pattern nicht nutzen. Erstelle einfach ein Objekt für jeden Service und gut. Ist absolut in Ordnung.


Objekt an Konstruktor übergeben.
Hier hast du 2 Möglichkeiten:

a) manuell
b) Dependency Injection nutzen.



Denke damit dürfte ich alles genannt haben. Ist zumindest das, was mir jetzt ausm Stehgreif einfällt und meine auch gelesen zu haben. Aus persönlicher Erfahrung würde ich von static Methoden abraten und ein DI-Framework nutzen. Das nimmt dir nämlich all deine Probleme auf elegante Art und Weiße ab. Und du bist damit auch flexibel genug jederzeit einfach die Implementierung durch eine komplett andere auszutauschen oder deren Scope (Singleton: ja/nein).

Hallo @all,

vielen Dank noch einmal für eure zahlreichen Kommentare und die angeregte Diskussion :slight_smile:

Da mir DI dahingehend unbekannt ist, das ich es nicht gezielt einsetzen kann, werder ich mich in der kommenden Zeit damit einmal intensiv auseinander setzen.

Da ich keinen Leidensdruck habe, werde ich mit der weiteren Entwicklung solange warten, bis ich mich in DI eingearbeitet habe. Falls ich bei DI kein Land sehen sollte, werde ich auf die statischen Methoden mit internem Objekt zurück greifen, wie es @Marco13 und @Tomate_Salat beschrieben haben.


Da dieser Beitrag hier mein erster hier im Forum war, möchte ich auch mal zum Ausdruck bingen, das man hier sehr gut behandelt wird. Es ist nicht ein Kommentar darüber gefallen, was das für eine dumme Frage sein könnte oder ähnliches, so wie es in anderen Foren oft üblich ist. Alles war schön sachlich, finde ich toll … weiter so. Es war schön mit euch diese Diskussion geführt zu haben :slight_smile: THX

Grüße


achja, da ich nicht weiß, wie ich den Beitrag als erledigt kennzeichnen kann, würde ich mich freuen, wenn das jemand von euch übernehmen könnte … THX :slight_smile:

Ein langer Thread, viele Gute Ratschlaege, hab mir ehrlich gesagt nicht alles durchgelesen, aber vielleicht einfach mal einfach machen :wink:

Versuche doch mal:

  • gar keine statische Methode zu verwenden
  • Parameter im Konstruktor zu uebergeben

Dadurch sollten ein paar Dinge wie Abhaengigkeiten und Struktur schon viel klarer werden :slight_smile: