Status:
Antworten von Fendy und Glen Best sind gleichermaßen akzeptabel und werden von mir geehrt, aber da man akzeptiert werden kann und Kopfgeld gegeben wird, wähle ich Fendys Antwort.
Scenario:
Wenn ich einen Code habe, der mehrfach in vielen Klassen wiederverwendet werden muss (selten mit geringfügigen Parameteränderungen, was offensichtlich ist) und gleichzeitige Threads, Welcher Ansatz gilt?
Der Code, der wiederverwendet werden muss, kann ein vernünftiger Code sein (mit angemessener Sorgfalt in Bezug auf den statischen und nicht-statischen Kontext im Kopf und Methoden zur Erstellung von Methoden). Es kann ein Algorithmus sein, eine DB-Methode, die verbindet, operiert, schließt. Alles.
Machen Sie eine Klasse wie MyMethods.class
und setzen Sie alle diese Methoden ein .
1.a. Machen Sie Methoden static
und rufen Sie (von allen Klassen und gleichzeitigen Threads) direkt als MyMethods.someMethod();
1.b. Machen Sie Methoden non-static
und zu der Zeit, um sie aufzurufen, instantiate
die ganze Klasse von MyMethods mm = MyMethods(); mm.someMethod();
Verwenden Sie das Strategie-Muster unter Ссылка (hier angehängter Code).
Verwenden Sie die Abhängigkeitsinjektion , die unter Ссылка
Problems:
Manche Leute würden sagen Komponententest Ссылка wird nicht möglich sein > Bei diesem Ansatz wird Schwierigkeiten beim Austauschen machen. Wenn Sie Ihre Klasse testen und eine Mock-Version der Abhängigkeit
verwenden möchten 1.a. Wird es Probleme mit gleichzeitigen Anrufen oder mehreren Klassen geben? speziell in JDBC static methods
für nur ein Beispiel?
1.b. Ich denke, es würde zu viel Speicherlast machen, da eine ganze Klasse instanticated
wäre, um nur eine oder zwei Methoden aufzurufen
Das ist weit über meinem Kopf, erklären Sie das und oder irgendwelche Vorteile / Nachteile
Ich möchte nicht ein Framework im Zusammenhang mit dieser Frage verwenden. Das ist weit über meinem Kopf, erkläre das und oder irgendwelche Vorteile / Nachteile
Warten auf andere Strategien oder Empfehlungen, falls vorhanden.
Request:
Bitte antworten Sie nur, wenn Sie erfahren sind und die Implikationen genau kennen und umfassend und mit Ihrer Antwort mir und der Gemeinschaft als Ganzes helfen können!
Code:
Ihre Frage hat eigentlich zwei Bedeutungen.
das in vielen Klassen viele Male wiederverwendet werden muss
Dies kann ein Kontext von Entwurfsmustern (wiederverwendbare Komponente) oder Speicherkosten (Klasseninstanziierung) sein. Aus zwei verschiedenen Perspektiven sprechen:
Dieser Abschnitt behandelt eigentlich nur zwei Arten von Instanziierung.
Zuerst ist statisch (oder DI-Instanziierung im Kompositionswurzel)
Nicht statisch
Kurz gesagt: Statische Kosten sind hoch, wenn die Klasse viele ist, und nicht-statische Kosten sind hoch, wenn die Anfrage hoch ist (zum Beispiel für for-Schleife). Aber es sollte Ihre Bewerbung nicht schwer machen. Die meisten Operationen in java / csharp sind jedoch Objekte erstellen.
1 - mega monolithischer Code (eine Gottklasse, die fast alles kann)
Vorteile:
Nachteile:
1a / statische Klasse / Singleton-Muster
Vorteile:
Nachteile:
Einige Punkte zur statischen Klasse: siehe diese Frage
2 Strategie-Muster
Eigentlich hat dies das gleiche Design mit 3 oder composition over inheritance
.
3 Abhängigkeitsinjektion
Vorteile:
Der Nachteil:
Ich denke, dass Staaten wichtige Regeln in Ihrem Anwendungsdesign spielen. Normalerweise versuchen Entwickler, Zustände im Geschäftslogikcode zu vermeiden, wie zum Beispiel:
%Vor% Entwickler neigen dazu, die Logik in andere Must be stateless
-Klasse oder zumindest Methoden wie:
Es wird eine bessere Lesbarkeit bieten und einfacher für Modifizierungs- und Komponententests sein. Es gibt auch ein Entwurfsmuster stateless
, um insbesondere solche Fälle zu behandeln.
IMHO, dieses Prinzip hat den größten Nutzen, wenn es befolgt wird. Die Vorteile sind:
Dieser Entwurf garantiert nicht, dass Ihr Code frei von Fehlern ist. Im Gegensatz zu Kosten für die Design-Phase und Layering-Aufwand hat es den Vorteil von:
Anti-Pattern für Service Locator
Verwenden von Decorator als Querschnittsaufgabe
Meine 2 Cent:
Der Vorteil der Verwendung der Schnittstelle (gilt auch für die Zusammensetzung der Vererbung)
Diese Designs und Strategien sind nicht der Schlüssel, der Ihre Anwendungsstruktur bestimmt. Es ist immer noch der Architekt, der es bestimmen wird. Ich bevorzuge es, einigen Prinzipien wie SOLID, KISS und GRASP zu folgen, anstatt zu entscheiden, was die beste Struktur ist. Es wird gesagt, dass Dependency Injection den meisten dieser Prinzipien folgt, aber zu viel Abstraktion und falsches Design der Komponenten führt zu dem Missbrauch von Singleton-Mustern.
1.a. Machen Sie Methoden statisch und rufen Sie (von allen Klassen und gleichzeitigen Threads) direkt als MyMethods.someMethod ();
auf1.b. Machen Sie Methoden nicht statisch und initialisieren Sie die gesamte Klasse zu dem Zeitpunkt, zu dem sie aufgerufen werden. MyMethods mm = MyMethods (); mm.someMethod ();
Die Wahl zwischen diesen beiden hängt von der Funktionalität von MyMethods.class
ab. Wenn MyMethods
zustandslos sein soll, dann ist es ein guter Ansatz, mit static
Methoden zu gehen. Andernfalls, wenn ein Methodenaufruf von einem anderen abhängt und MyMethods
über Zustände (d. H. Nicht endgültige Felder) verfügt, verwenden Sie die zweite Option.
Verwenden Sie das in Ссылка angegebene Strategie-Muster (Code hier beigefügt).
Verwenden Sie dieses Muster, wenn MyMethods
mit verschiedenen Klassen für verschiedene Zwecke erweitert werden soll und Sie auswählen, welcher Code abhängig von Ihrem Kontext ausgeführt werden soll. Wie das Wiki sagt, wenn Sie den zu verwendenden Algorithmus vor der Laufzeit nicht kennen (hängt von einigen Bedingungen ab), ist dies der richtige Weg. Gemäß Ihrer Spezifikation von MyMethods
haben Sie solche Probleme nicht.
Verwenden Sie die Abhängigkeitsinjektion, die unter Ссылка
angegeben ist
Gleiche Antwort wie oben. Die Sache mit Abhängigkeitsinjektion ist in Inversion der Kontrolle . Eine Klasse, die MyMethods
verwendet, weiß nicht über die tatsächliche Implementierung von MyMethods
, aber die Injektion der realen Implementierung wird an eine höhere Autorität delegiert. Es abstrahiert externe Abhängigkeiten aus dem Kontext, in dem es verwendet werden soll. Wenn MyMethods
wieder zustandslos und konstant sein soll (nicht geplant, sich zu ändern, und das Verhalten der Methoden in der Klasse nicht vom Kontext abhängt, in dem sie verwendet werden), brauchen Sie diese Muster nicht, da dies nur Übertechnik bedeuten würde .
Ich würde daraus schließen, dass Sie das Strategie oder DI Muster verwenden sollten, wenn die Logik von MyMethods
vom Kontext abhängt, aus dem sie ausgeführt werden. Wenn diese Konstante konstant ist (z. B. ob Javas Math
-Klasse egal ist, wer oder in welchem Kontext jemand sqrt()
, max()
oder pow()
aufruft), dann sind statische Methoden die richtige Wahl.
Bei Problemen:
Probleme, die Sie angegeben haben, sind nicht vorhanden, wenn Sie MyMethods
mit static
Methoden verwenden. Sie müssen testen, ob Ihre Methoden korrekte Werte für bestimmte Argumente liefern, und das war's. Ich glaube nicht, dass es viel mehr Probleme beim Testen der tatsächlichen Implementierung von Strategy
in Strategy pattern oder der Implementierung von Schnittstellen geben würde, die durch Dependency injection injiziert werden. Was vielleicht schwieriger ist, testet die Klassen, die die Strategie verwenden, weil es manchmal nicht einfach ist, den Kontext wiederherzustellen, in dem die bestimmte Strategie ausgeführt wird, da dies oft von Benutzereingaben abhängt, aber es ist definitiv nicht unmöglich. Die Abhängigkeitsinjektion ist meines Erachtens ideal zum Testen, da Sie die zu testende Einheit von einer Abhängigkeit trennen können, die Sie leicht verspotten können.
Die Hauptfrage: Wiederverwendung von Code
Wenn ich Code habe, der viele Male in vielen Klassen wiederverwendet werden muss (selten mit geringfügigen Parameteränderungen, was offensichtlich ist) und gleichzeitige Threads, welcher Ansatz ist zu beachten?
Weil Sie keine Schnitt- und Pasteten in Betracht ziehen, meinen Sie:
... viele Male von vielen Klassen wiederverwendet ...
Was Sie fragen, ist nichts Besonderes oder Spezifisches. Es ist üblich, dass Code entweder in einer einzelnen App oder in mehreren Apps wiederverwendet wird. Die allgemeine Antwort: Verwenden Sie objektorientiertes Design / Programmierung . Setzen Sie den Code in eine Klasse, erstellen Sie ein Objekt als Instanz, rufen Sie das Objekt ...
auf1a. Wiederverwendung über statische Methoden:
Machen Sie Methoden statisch und rufen Sie (durch alle Klassen und gleichzeitige Threads) direkt als MyMethods.someMethod ()
auf
1b. Wiederverwendung über nicht-statische Methoden, mit Objekt Instanziierung:
Machen Sie Methoden nicht-statisch und initialisieren Sie die ganze Klasse zu der Zeit, um sie aufzurufen, indem Sie MyMethods verwenden mm = MyMethods (); mm.someMethod ();
Verwenden Sie das Strategie-Muster
Strategie Muster kann gute Praxis sein. Aber es hat wenig mit Ihrer allgemeinen Frage zu tun. Das Strategie-Pattern wird aus einem bestimmten Grund verwendet - um die Implementierung des Algorithmus / der Verarbeitungslogik "on-the-fly" zu vertauschen, ohne den Aufrufer zu beeinflussen.
Verwenden Sie die Abhängigkeitsinjektion
Die Abhängigkeitsinjektion wird aus folgenden Gründen verwendet:
Dies kann eine sehr gute Übung sein, wenn es entsprechend verwendet wird. In Ihrem Fall könnte dies nur unter Option 1b gelten. Bei der Abhängigkeitsinjektion geht es um die Instanziierung und Bereitstellung von Objekten in Variablen.
Probleme:
Einige Leute würden sagen, Unit-Test wird nicht möglich sein
1a. Siehe oben
1b. Speicher laden
Ich denke, es würde zu viel Speicher laden, da eine ganze Klasse viele Male instantiiert werden würde, um nur eine oder zwei Methoden aufzurufen.
Ein kleines Problem. Abhängig von den Daten innerhalb jeder Objektinstanz (den Instanzvariablen) kann jede Objektinstanz so klein wie ein Dutzend Bytes oder so groß wie Megabytes sein - aber normalerweise zum unteren Ende geneigt (oft & lt; 1kB). Der Speicherverbrauch der Klasse code selbst wird nicht jedes Mal repliziert, wenn die Klasse instanziiert wird.
Natürlich ist es eine gute Übung, das Volumen von Objekten entsprechend Ihren Anforderungen zu minimieren. Erstellen Sie keine neue Instanz, wenn Sie bereits eine verwendbare haben. Erstellen Sie weniger Objektinstanzen und teilen Sie sie in Ihrer App auf, indem Sie sie an Konstruktormethoden und Setter-Methoden übergeben. Die Abhängigkeitsinjektion ist eine gute Möglichkeit, Objektinstanzen "automatisch" zu teilen, ohne sie an Konstruktoren / Setter zu übergeben.
Siehe oben
Siehe oben
Tags und Links java class unit-testing design-patterns dependency-injection