Namen haben die Möglichkeit, Bedeutung zu vermitteln. Warum sollten Sie diese Gelegenheit mit Impl verpassen?
Zunächst einmal, wenn Sie immer nur eine Implementierung haben, tun , weg mit der Schnittstelle. Es verursacht dieses Benennungsproblem und fügt nichts hinzu. Schlimmer noch, es kann Probleme mit inkonsistenten Methodensignaturen in APIs verursachen, wenn Sie und alle anderen Entwickler nicht darauf achten, immer nur die Schnittstelle zu verwenden.
Vorausgesetzt, wir können davon ausgehen, dass jede Schnittstelle zwei oder mehr Implementierungen hat oder haben kann .
Wenn Sie im Moment nur eine haben und nicht wissen, inwiefern sich die andere unterscheidet, ist Default ein guter Anfang.
Wenn Sie gerade zwei haben, benennen Sie jede nach ihrem Zweck.
Beispiel: Vor kurzem hatten wir eine konkrete Klasse Context (in Bezug auf eine Datenbank). Es wurde erkannt, dass wir in der Lage sein mussten, einen Kontext darzustellen, der offline war. Daher wurde der Name Context für eine neue Schnittstelle verwendet (um die Kompatibilität für alte APIs aufrechtzuerhalten), und eine neue Implementierung wurde erstellt, OfflineContext . Aber raten Sie mal, in was das Original umbenannt wurde? Das ist richtig, ContextImpl (yikes).
In diesem Fall wäre DefaultContext wahrscheinlich in Ordnung , und die Leute würden es bekommen, aber es ist nicht so beschreibend, wie es sein könnte. Wenn es nicht offline ist , was ist es dann? Also gingen wir mit: OnlineContext .
Sonderfall: Verwenden des Präfix "I" bei Schnittstellen
Eine der anderen Antworten schlug vor, das Präfix I für Schnittstellen zu verwenden. Vorzugsweise müssen Sie nicht brauchen , dies zu tun.
Wenn Sie jedoch für benutzerdefinierte Implementierungen sowohl eine Schnittstelle als auch eine konkrete Primärimplementierung benötigen , die häufig verwendet wird, und der grundlegende Name dafür einfach zu einfach ist, um auf eine Schnittstelle allein zu verzichten, können Sie das Hinzufügen in Betracht ziehen "Ich" zur Benutzeroberfläche (obwohl es völlig in Ordnung ist, wenn es für Sie und Ihr Team immer noch nicht richtig ist).
Beispiel: Viele Objekte können ein "EventDispatcher" sein. Für APIs muss dies einer Schnittstelle entsprechen. Sie möchten jedoch auch einen einfachen Ereignis-Dispatcher für die Delegierung bereitstellen . DefaultEventDispatcher wäre in Ordnung, aber es ist etwas lang, und wenn Sie den Namen häufig sehen, ziehen Sie es möglicherweise vor, den Basisnamen EventDispatcher für die konkrete Klasse zu verwenden und IEventDispatcher für benutzerdefinierte Implementierungen zu implementieren:
/* Option 1, traditional verbose naming: */
interface EventDispatcher { /* interface for all event dispatchers */ }
class DefaultEventDispatcher implements EventDispatcher {
/* default event dispatcher */
}
/* Option 2, "I" abbreviation because "EventDispatcher" will be a common default: */
interface IEventDispatcher { /* interface for all event dispatchers */ }
class EventDispatcher implements IEventDispatcher {
/* default event dispatcher. */
}
if you will only ever have one implementation, do away with the interface
- es sei denn, Sie möchten die Komponente testen. In diesem Fall möchten Sie möglicherweise diese Schnittstelle beibehalten, um MockOrder, OrderStub oder ähnliches zu erstellen.Ich entscheide die Benennung durch den Anwendungsfall der Schnittstelle.
Wenn die Schnittstelle zur Entkopplung verwendet wird , entscheide ich mich
Impl
für Implementierungen.Wenn der Zweck der Schnittstelle die Abstraktion des Verhaltens ist , werden die Implementierungen entsprechend ihrer konkreten Vorgehensweise benannt. Ich füge oft den Schnittstellennamen hinzu. Also wenn die Schnittstelle aufgerufen wird
Validator
, benutze ichFooValidator
.Ich finde, das
Default
ist eine sehr schlechte Wahl. Zunächst werden Code-Vervollständigungsfunktionen verschmutzt, da die Namen immer damit beginnen. Die andere Sache ist, dass sich ein Standard im Laufe der Zeit ändern kann. Was also als erstes ein Standard sein könnte, kann einige Zeit später ein veraltetes Feature sein. Entweder benennen Sie Ihre Klassen immer um, sobald sich die Standardeinstellungen ändern, oder Sie leben mit irreführenden Namen.quelle
Ich bin mit Nicoles Antwort einverstanden (insbesondere, dass die Schnittstelle in den meisten Fällen wahrscheinlich nicht erforderlich ist), aber zur Erörterung werde ich eine andere Alternative als
OrderImpl
und ausschließenDefaultOrder
: Verstecke die Implementierung hinter einer statischen Factory-Methode wieOrders.create()
. Beispielsweise:Bei diesem Ansatz kann es sich bei der Implementierung um eine anonyme innere Klasse handeln, oder es kann sich um eine private Klasse mit
Default
oderImpl
im Namen handeln, oder es kann ein ganz anderer Name verwendet werden. Unabhängig davon, welche Wahl getroffen wird, muss sich der Anrufer nicht darum kümmern, sodass Sie jetzt und später mehr Flexibilität erhalten, wenn Sie sich entscheiden, diese zu ändern.Einige gute Beispiele für dieses Muster in der Praxis sind die Klassen
java.util.Collections
undjava.util.concurrent.Executors
utility, deren Methoden versteckte Implementierungen zurückgeben. Wie Effective Java (in Punkt 1) erwähnt, kann dieses Muster dazu beitragen, das "konzeptionelle Gewicht" der API kleiner zu halten.quelle
Ich gehe immer
OrderImpl
einfach so vor, weil es direkt nach demOrder
Interface in alphabetischer Reihenfolge angezeigt wird.quelle
Sie können die Schnittstelle mit dem Präfix I (IWhatever) benennen und dann die Implementierung Whatever vornehmen.
Offizielle Java-Code-Konventionen beschreiben diese Art der Benennung von Schnittstellen nicht, diese Art der Benennung hilft jedoch bei der Erkennung und Navigation.
quelle
Ich denke, dass Default in einigen Fällen sinnvoll sein kann, es aber hilfreicher wäre, die Implementierung zu beschreiben. Also, wenn Ihre Schnittstelle ist,
UserProfileDAO
dann können Ihre ImplementierungenUserProfileSQLDAO
oderUserProfileLDAPDAO
oder so ähnlich sein.quelle
wenn möglich, benenne es nach was / wie es seine Sache macht.
Normalerweise ist es der schlechteste Ansatz, ihn nach der Art und Weise zu benennen, wie er verwendet werden soll.
Wenn es als Basisklasse für die Implementierung verwendet werden soll, können Sie BaseX oder AbstractX verwenden (wenn es abstrakt ist). Versuchen Sie jedoch, die Funktionen zu verfeinern, da Sie es bereits erstellt haben, wenn es nichts getan hätte Schnittstelle) .Wenn es die einfachstmögliche Funktionalität bietet und erwartet wird, dass es direkt verwendet wird (ohne es zu erweitern), wenn eine solche Funktionalität ausreicht, können Sie es SimpleX oder BasicX nennen.
Wenn es verwendet wird, sofern keine andere Implementierung bereitgestellt wird, nennen Sie es DefaultX
quelle
Die meisten dieser Antworten beschreiben, was getan wird, aber nicht warum.
Was ist mit den OO-Prinzipien passiert? Was sagt Impl zu einer Klasse und wie benutze ich sie? Sie sollten sich Gedanken darüber machen, wie die Verwendung und nicht wie sie aufgebaut ist.
Was ist ein PersonImpl, wenn ich eine Personenschnittstelle erstelle? Bedeutungslos. Zumindest sagt mir DefaultPerson, wer auch immer codiert hat, er sollte keine Schnittstelle erstellen.
Schnittstellen tippen auf Polymorphismus und sollten als solche verwendet werden.
quelle