Wenn ich eine Utility-Klasse entwerfen muss (z. B. ByteUtils oder StreamUtils oder StringUtils), welche ist die beste Entwurfsoption für sie?
- Sollten es statische Klassen sein (da ich keine Zustände zum Speichern habe)
- Sollten sie nicht statische Klassen sein (wenn die Objekte nicht verwendet werden, werden sie gc'd)
PS: Mit statischer Klasse meinte ich eine Klasse mit statischen Methoden (und nicht die innere statische Klasse).
Bitte geben Sie Ratschläge zur Auswahl des Designs.
Antworten:
Wenn es sich um ein Allzweckdienstprogramm handelt, ist statisch IMO besser. Sie haben angegeben, dass Sie keine zu speichernden Status haben werden, daher verstehe ich nicht, warum Sie sie nicht statisch machen sollten. Wenn Sie es als statisch deklarieren, wird auch Speicherplatz gespart.
quelle
Meine Utility-Klassen sehen folgendermaßen aus:
// final, because it's not supposed to be subclassed public final class FooUtil { // private constructor to avoid unnecessary instantiation of the class private FooUtil() { } public static int doSomethingUseful() { } // ... }
Beachten Sie, dass die Dienstprogrammmethoden zwar leicht testbar und von außen leicht zugänglich sind, die Klassen, die sie verwenden, jedoch auch schwer zu testen sind, da es nicht einfach ist, diese Dienstprogrammmethoden zu verspotten. Zu viele solcher Dienstprogrammklassen können ein Zeichen für einen Mangel an OO-Design (prozedurale Programmierung) sein und den Code wirklich schwer testen.
Wenn Sie ein Abhängigkeitsinjektionsframework (Spring, Guice, was auch immer) verwenden, ist es möglicherweise eine gute Idee, die Utility-Klasse mit nicht statischen Methoden instanziierbar zu machen und sie zu einem injizierbaren Singleton zu machen. Auf diese Weise können Klassen, die diese Dienstprogrammmethoden verwenden, getestet werden, indem das Dienstprogrammobjekt verspottet wird.
quelle
Nur weil etwas statisch sein kann, heißt das nicht, dass es statisch sein sollte.
Es gibt noch eine andere Überlegung: Spott. Es ist schwieriger, statische Methoden in Ihren Tests zu verspotten, als das Verhalten einer Instanz einer Klasse zu verspotten.
Die Rede von unnötigen Heap-Zuordnungen und GCing von Objekten riecht für mich nach vorzeitiger Optimierung. Die JVM wird ziemlich gute Arbeit leisten, um diese Art von Problem zu beseitigen.
quelle
Der einfachste Weg, eine Utility-Klasse zu definieren, ist eine Aufzählung ohne Instanzen
public enum Utility {; public static int utilityMethod(int x) { /* ... */ } }
Eine Utility-Klasse sollte keinen oder nur einen minimalen Status haben, sodass Sie sich keine Gedanken über GCs machen sollten.
Sie können andere zustandsbehaftete Klassen für bestimmte Zwecke wie Builder oder Factory verwenden. Sie können das Objekt wie gewünscht erstellen und es verwerfen, wenn Sie fertig sind.
quelle
final
standardmäßig.enum
können veränderbare Felder vorhanden sein, Schnittstellen und abstrakte Methoden implementieren, sodass sie viel mehr als nur Konstanten sind. ;)enum
in die Mischung ändert jedoch, wie der müde Ingenieur um 3 Uhr morgens auf Koffein hüpft, das Ding liest und ihn für einen Moment fragen lässt, was los ist. Es ist einfach keine übliche Redewendung. Nutzeclass
und sei glücklich.enum
, können Sie für den Leser sind telegraphing dass es einen Grund für die Zählung in seinem Design versteckt ist. Das gibt es nicht. Sie versuchen nur, es einfacher zu machen, als einenfinal
privaten Konstruktor einzubauen, von denen keines IMO ein Problem darstellt. Das ist eine ungewöhnliche Redewendung. Und Sie haben jemanden gesehen, der versucht hat, eine Klasse statischer Dienstprogrammmethoden zu instanziieren? Ist das wichtig? Wenn jemand sieht, dass die Klasse die Methoden liefert, die er benötigt, weiß er, was er ist ---- warum sollte er sie instanziieren? Und was passiert, wenn sie es taten? Nicht viel.Es ist gut, die Klasse mit einem privaten Konstruktor als nicht statisch zu machen:
quelle
Normalerweise enthalten Dienstprogrammklassen statische Methoden und keine Attribute. Dieser Ansatz erleichtert die Verwendung ihrer Methoden, ohne die Klasse zu instanziieren. Hoffe das hilft.
quelle
Wenn Sie sie statisch machen können, dann tun Sie dies auf jeden Fall!
Mit anderen Worten, wenn sie keinen Status haben, sollten sie statisch sein.
quelle
Nun, wenn Sie keinen Status zum Speichern haben, gibt es nichts zu GC, also würde ich mit statisch gehen, auf diese Weise vermeiden Sie unnötige Heap-Zuweisungen und GC.
quelle
Reine Dienstprogrammklassen sollten normalerweise statisch sein. Wenn Sie eine Klasse mit genau definierter Eingabe und Ausgabe, ohne Nebenwirkungen und ohne Status haben, sollte es per Definition eine statische Klasse sein.
Fügen Sie im Allgemeinen keine Komplexität hinzu (in diesem Fall Abhängigkeitsinjektion), bevor dies erforderlich ist, und dies hat einen Vorteil.
quelle
Niemand erwähnt hier, dass statische Dienstprogrammmethoden nicht erweiterbar sind. Sie können sie nicht überschreiben. Sie können OOP nicht nutzen (insbesondere Polymorphysmus, das mächtigste Merkmal von OOP). Das führt zu einer Codeduplizierung.
PS Ich fand diesen Artikel sehr hilfreich. http://www.yegor256.com/2014/05/05/oop-alternative-to-utility-classes.html
quelle