webentwicklung-frage-antwort-db.com.de

Klasse mit einer Methode - Bester Ansatz?

Angenommen, ich habe eine Klasse, die eine einzelne Funktion ausführen soll. Nach Ausführung der Funktion kann diese zerstört werden. Gibt es einen Grund, einen dieser Ansätze zu bevorzugen?

// Initialize arguments in constructor
MyClass myObject = new MyClass(arg1, arg2, arg3);
myObject.myMethod();

// Pass arguments to method
MyClass myObject = new MyClass();
myObject.myMethod(arg1, arg2, arg3);

// Pass arguments to static method
MyClass.myMethod(arg1, arg2, arg3);

Ich war absichtlich vage über die Details, um zu versuchen, Richtlinien für verschiedene Situationen zu erhalten. Aber ich hatte nicht wirklich einfache Bibliotheksfunktionen wie Math.random () im Sinn. Ich denke eher an Klassen, die eine bestimmte, komplexe Aufgabe ausführen, für die jedoch nur eine (öffentliche) Methode erforderlich ist.

163
JW.

Ich liebte Utility-Klassen, die mit statischen Methoden gefüllt waren. Sie haben eine großartige Konsolidierung von Hilfsmethoden vorgenommen, die andernfalls Redundanz und Wartungsaufwand verursachen würden. Sie sind sehr einfach zu bedienen, keine Instantiierung, keine Entsorgung, nur Feuer und Vergessen. Ich denke, dies war mein erster unbeabsichtigter Versuch, eine serviceorientierte Architektur zu schaffen - viele zustandslose Services, die nur ihren Job gemacht haben und sonst nichts. Während ein System wächst, kommen jedoch Drachen.

Polymorphismus
Sagen wir, wir haben die Methode UtilityClass.SomeMethod, die glücklich mitschwirrt. Plötzlich müssen wir die Funktionalität etwas ändern. Der größte Teil der Funktionalität ist derselbe, aber wir müssen trotzdem einige Teile ändern. Wäre es keine statische Methode gewesen, könnten wir eine Derivate-Klasse erstellen und den Methodeninhalt nach Bedarf ändern. Da es eine statische Methode ist, können wir nicht. Klar, wenn wir nur Funktionalität vor oder nach der alten Methode hinzufügen müssen, können wir eine neue Klasse erstellen und die alte in ihr aufrufen - aber das ist nur eklatant.

Probleme mit der Benutzeroberfläche
Statische Methoden können aus logischen Gründen nicht über Schnittstellen definiert werden. Und da wir statische Methoden nicht überschreiben können, sind statische Klassen nutzlos, wenn wir sie über ihre Schnittstelle weitergeben müssen. Dies macht es uns unmöglich, statische Klassen als Teil eines Strategiemusters zu verwenden. Wir können einige Probleme beheben, indem wir Delegierte anstelle von Schnittstellen übergeben .

Testen
Dies geht im Grunde mit den oben erwähnten Problemen der Benutzeroberfläche einher. Da wir nur sehr eingeschränkte Möglichkeiten haben, Implementierungen auszutauschen, können wir auch den Produktionscode nicht durch Testcode ersetzen. Wir können sie wieder einpacken, müssen jedoch große Teile unseres Codes ändern, um Wrapper anstelle der eigentlichen Objekte akzeptieren zu können.

Fördert Blobs
Da statische Methoden in der Regel als Dienstprogrammmethoden verwendet werden und Dienstprogrammmethoden in der Regel unterschiedliche Zwecke haben, erhalten wir schnell eine große Klasse mit nicht kohärenter Funktionalität - im Idealfall sollte jede Klasse einen einzigen Zweck haben innerhalb des Systems. Ich hätte viel lieber eine fünffache Klasse, solange ihre Ziele klar definiert sind.

Parameter Creep
Zunächst könnte diese kleine nette und unschuldige statische Methode einen einzigen Parameter annehmen. Mit zunehmender Funktionalität werden einige neue Parameter hinzugefügt. Bald werden weitere Parameter hinzugefügt, die optional sind, sodass wir Überladungen der Methode erstellen (oder einfach Standardwerte in Sprachen hinzufügen, die diese unterstützen). In Kürze haben wir eine Methode, die 10 Parameter akzeptiert. Nur die ersten drei sind wirklich erforderlich, Parameter 4-7 sind optional. Wenn jedoch Parameter 6 angegeben wird, müssen auch 7-9 ausgefüllt werden. Hätten wir eine Klasse mit dem einzigen Zweck erstellt, das zu tun, was diese statische Methode getan hat, könnten wir dies lösen, indem wir die erforderlichen Parameter in das Feld eingeben Der Benutzer kann optionale Werte über Eigenschaften oder Methoden festlegen, um mehrere voneinander abhängige Werte gleichzeitig festzulegen. Wenn eine Methode auf diese Komplexität angewachsen ist, muss sie höchstwahrscheinlich sowieso in ihrer eigenen Klasse sein.

Fordert die Konsumenten auf, ohne Grund eine Instanz von Klassen zu erstellen
Eines der häufigsten Argumente ist, warum die Verbraucher unserer Klasse aufgefordert werden, eine Instanz zum Aufrufen dieser einzelnen Methode zu erstellen, ohne die Instanz danach zu verwenden. Das Erstellen einer Instanz einer Klasse ist in den meisten Sprachen eine sehr, sehr kostengünstige Operation, daher spielt Geschwindigkeit keine Rolle. Das Hinzufügen einer zusätzlichen Codezeile für den Verbraucher ist mit geringen Kosten verbunden, um den Grundstein für eine in Zukunft viel wartbarere Lösung zu legen. Wenn Sie keine Instanzen erstellen möchten, erstellen Sie einfach einen Singleton-Wrapper für Ihre Klasse, der eine einfache Wiederverwendung ermöglicht. Dies setzt jedoch voraus, dass Ihre Klasse statusfrei ist. Wenn es nicht zustandslos ist, können Sie dennoch statische Wrapper-Methoden erstellen, die alles verarbeiten und Ihnen auf lange Sicht dennoch alle Vorteile bieten. Schließlich können Sie auch eine Klasse erstellen, die die Instanziierung als Singleton verbirgt: MyWrapper.Instance ist eine Eigenschaft, die nur new MyClass () zurückgibt.

Nur ein Sith handelt in absoluten Zahlen
Natürlich gibt es Ausnahmen von meiner Abneigung gegen statische Methoden. Echte Utility-Klassen, die kein Aufblähungsrisiko darstellen, eignen sich hervorragend für statische Methoden - beispielsweise System.Convert. Wenn es sich bei Ihrem Projekt um ein Einzelprojekt handelt, für das keine zukünftigen Wartungsarbeiten erforderlich sind, spielt die Gesamtarchitektur keine große Rolle - statisch oder nicht statisch, spielt jedoch keine Rolle - die Entwicklungsgeschwindigkeit.

Standards, Standards, Standards!
Die Verwendung von Instanzmethoden hindert Sie nicht daran, auch statische Methoden zu verwenden und umgekehrt. Solange die Unterscheidung begründet und standardisiert ist. Es gibt nichts Schlimmeres, als einen Blick auf eine Business-Schicht zu werfen, die sich aus verschiedenen Implementierungsmethoden zusammensetzt.

256

Ich bevorzuge den statischen Weg. Da die Klasse kein Objekt darstellt, ist es nicht sinnvoll, eine Instanz davon zu erstellen.

Klassen, die nur für ihre Methoden existieren, sollten statisch bleiben.

86
jjnguy

Wenn es keinen Grund gibt, eine Instanz der Klasse erstellen zu lassen, um die Funktion auszuführen, verwenden Sie die statische Implementierung. Warum sollen die Konsumenten dieser Klasse eine Instanz erstellen, wenn eine nicht benötigt wird?.

17
Ray Jezek

Wenn Sie das state des Objekts nicht speichern müssen, müssen Sie es nicht erst instanziieren. Ich würde mit der einzelnen statischen Methode gehen, an die Sie Parameter übergeben.

Ich würde auch vor einer riesigen Utils-Klasse warnen, die Dutzende nicht verwandter statischer Methoden hat. Dies kann in Eile unorganisiert und unhandlich werden. Es ist besser, viele Klassen mit jeweils wenigen verwandten Methoden zu haben.

15
Bill the Lizard

Ich würde sagen, dass das statische Methodenformat die bessere Option wäre. Und ich würde die Klasse auch statisch machen, auf diese Weise müssten Sie sich nicht darum kümmern, versehentlich eine Instanz der Klasse zu erstellen.

6
Nathen Silver

Ich weiß wirklich nicht, wie es hier aussieht, aber ich würde es als Methode in eine der Klassen einordnen, zu denen arg1, arg2 oder arg3 gehören Methode.

5
Chris Cudmore

Ich würde vorschlagen, dass es schwierig ist, basierend auf den bereitgestellten Informationen zu antworten.

Ich bin der Meinung, wenn Sie nur eine Methode haben und die Klasse sofort wegwerfen wollen, dann machen Sie sie zu einer statischen Klasse, die alle Parameter übernimmt.

Natürlich ist es schwierig, genau zu sagen, warum Sie eine einzelne Klasse nur für diese eine Methode erstellen müssen. Ist es die typische "Versorgungsklasse" Situation, wie die meisten annehmen? Oder implementieren Sie eine Art Regelklasse, von der es in Zukunft möglicherweise mehr geben wird?.

Lassen Sie diese Klasse zum Beispiel steckbar sein. Dann möchten Sie ein Interface für Ihre eine Methode erstellen und dann möchten Sie, dass alle Parameter an das Interface und nicht an den Konstruktor übergeben werden, aber Sie möchten nicht, dass es statisch ist.

4
Nick

Kann Ihre Klasse statisch gemacht werden?

Wenn ja, dann würde ich es zu einer "Utilities" -Klasse machen, in die ich alle meine Ein-Funktions-Klassen einfügen würde.

3
Robert

Für einfache Anwendungen und internal Helfer würde ich eine statische Methode verwenden. Für Anwendungen mit Komponenten liebe ich das Managed Extensibility Framework . Hier ist ein Auszug aus einem Dokument, das ich schreibe, um die Muster zu beschreiben, die Sie in meinen APIs finden.

  • Dienstleistungen
    • Definiert durch ein I[ServiceName]Service Schnittstelle.
    • Exportiert und importiert nach Schnittstellentyp.
    • Die einzelne Implementierung wird von der Host-Anwendung bereitgestellt und intern und/oder von Erweiterungen verwendet.
    • Die Methoden auf der Dienstschnittstelle sind threadsicher.

Als konstruiertes Beispiel:

public interface ISettingsService
{
    string ReadSetting(string name);

    void WriteSetting(string name, string value);
}

[Export]
public class ObjectRequiringSettings
{
    [Import]
    private ISettingsService SettingsService
    {
        get;
        set;
    }

    private void Foo()
    {
        if (SettingsService.ReadSetting("PerformFooAction") == bool.TrueString)
        {
            // whatever
        }
    }
}
3
Sam Harwell

Wenn diese Methode zustandslos ist und Sie sie nicht weitergeben müssen, ist es am sinnvollsten, sie als statisch zu definieren. Wenn Sie die Methode weitergeben müssen, sollten Sie ein Delegat anstelle eines Ihrer anderen vorgeschlagenen Ansätze verwenden.

3
Joel Wietelmann

Ich würde einfach alles im Konstruktor machen. wie so:

new MyClass(arg1, arg2, arg3);// the constructor does everything.

oder

MyClass my_object(arg1, arg2, arg3);
2
yigal

ich denke, wenn Eigenschaften Ihrer Klasse oder die Instanz der Klasse nicht in Konstruktoren oder in Ihren Methoden verwendet werden, wird nicht vorgeschlagen, Methoden wie "statisches" Muster zu entwerfen. statische Methode sollte immer in "Hilfe" gedacht werden.

0
user7545070

Eine weitere wichtige Frage ist, ob das System in einer Multithread-Umgebung ausgeführt wird und ob eine statische Methode oder Variablen threadsicher sind ...

Sie sollten auf den Systemstatus achten.

0
NZal

Möglicherweise können Sie die Situation insgesamt vermeiden. Versuchen Sie, so umzugestalten, dass Sie arg1.myMethod1(arg2, arg3) erhalten. Tauschen Sie arg1 entweder mit arg2 oder arg3 aus, wenn dies sinnvoller ist.

Wenn Sie nicht die Kontrolle über die Klasse von arg1 haben, dann dekorieren Sie sie:

class Arg1Decorator
    private final T1 arg1;
    public Arg1Decorator(T1 arg1) {
        this.arg1 = arg1;
    }
    public T myMethod(T2 arg2, T3 arg3) {
        ...
    }
 }

 arg1d = new Arg1Decorator(arg1)
 arg1d.myMethod(arg2, arg3)

Der Grund dafür ist, dass in OOP Daten und Methoden, die diese Daten verarbeiten, zusammengehören. Außerdem erhalten Sie alle Vorteile, die Mark erwähnt hat.

0
Hugo Wood