Man stößt auf diesen Satz, wenn man über Designmuster liest.
Aber ich verstehe es nicht, könnte mir das jemand erklären?
oop
design-patterns
interface
software-design
ooad
Never_had_a_name
quelle
quelle
Antworten:
Codierung gegen Schnittstelle bedeutet, dass der Client-Code immer ein Schnittstellenobjekt enthält, das von einer Fabrik geliefert wird. Jede von der Factory zurückgegebene Instanz wäre vom Typ Interface, den jede Factory-Kandidatenklasse implementiert haben muss. Auf diese Weise macht sich das Client-Programm keine Sorgen um die Implementierung und die Schnittstellensignatur bestimmt, was alle Vorgänge ausgeführt werden können. Dies kann verwendet werden, um das Verhalten eines Programms zur Laufzeit zu ändern. Es hilft Ihnen auch, aus Sicht der Wartung weitaus bessere Programme zu schreiben.
Hier ist ein einfaches Beispiel für Sie.
BEARBEITEN
Ich habe das obige Beispiel aktualisiert und eine abstrakte
Speaker
Basisklasse hinzugefügt . In diesem Update habe ich "SayHello" allen Lautsprechern eine Funktion hinzugefügt. Alle Sprecher sprechen "Hallo Welt". Das ist also ein gemeinsames Merkmal mit ähnlicher Funktion. Wenn Sie sich das Klassendiagramm ansehen, werden Sie feststellen, dass dieSpeaker
abstrakte Klasse dieISpeaker
Schnittstelle implementiert undSpeak()
als abstrakt markiert. Dies bedeutet, dass jede Speaker-Implementierung für die Implementierung derSpeak()
Methode verantwortlich ist, da sie vonSpeaker
bis variiertSpeaker
. Aber alle Redner sagen einstimmig "Hallo". In der abstrakten Speaker-Klasse definieren wir eine Methode mit der Aufschrift "Hello World", und jedeSpeaker
Implementierung leitet dieSayHello()
Methode ab.Stellen Sie sich einen Fall vor, in dem Sie
SpanishSpeaker
nicht Hallo sagen können. In diesem Fall können Sie dieSayHello()
Methode für Spanisch sprechend überschreiben und die richtige Ausnahme auslösen.Und wir könnten dieses Verhalten erreichen, indem wir einfach einen Sprecher der abstrakten Basisklasse und einige geringfügige Änderungen in jeder Implementierung hinzufügen, wodurch das ursprüngliche Programm unverändert bleibt. Dies ist eine gewünschte Funktion jeder Anwendung und macht Ihre Anwendung leicht wartbar.
quelle
List
als Typ verwenden, können Sie immer noch davon ausgehen, dass der Direktzugriff durch wiederholtes Aufrufen schnell istget(i)
.Stellen Sie sich eine Schnittstelle als Vertrag zwischen einem Objekt und seinen Kunden vor. Das heißt, die Schnittstelle gibt die Dinge an, die ein Objekt tun kann, und die Signaturen für den Zugriff auf diese Dinge.
Implementierungen sind die tatsächlichen Verhaltensweisen. Angenommen, Sie haben eine Methode sort (). Sie können QuickSort oder MergeSort implementieren. Dies sollte für den Clientcode, der sort aufruft, keine Rolle spielen, solange sich die Schnittstelle nicht ändert.
Bibliotheken wie die Java-API und .NET Framework verwenden häufig Schnittstellen, da Millionen von Programmierern die bereitgestellten Objekte verwenden. Die Ersteller dieser Bibliotheken müssen sehr vorsichtig sein, dass sie die Schnittstelle zu den Klassen in diesen Bibliotheken nicht ändern, da dies alle Programmierer betrifft, die die Bibliothek verwenden. Auf der anderen Seite können sie die Implementierung beliebig ändern.
Wenn Sie als Programmierer gegen die Implementierung codieren, funktioniert Ihr Code nicht mehr, sobald er sich ändert. Stellen Sie sich die Vorteile der Benutzeroberfläche folgendermaßen vor:
quelle
Dies bedeutet, dass Sie versuchen sollten, Ihren Code so zu schreiben, dass er eine Abstraktion (abstrakte Klasse oder Schnittstelle) anstelle der direkten Implementierung verwendet.
Normalerweise wird die Implementierung über den Konstruktor oder einen Methodenaufruf in Ihren Code eingefügt. Ihr Code kennt also die Schnittstelle oder die abstrakte Klasse und kann alles aufrufen, was in diesem Vertrag definiert ist. Wenn ein tatsächliches Objekt (Implementierung der Schnittstelle / abstrakte Klasse) verwendet wird, werden die Aufrufe für das Objekt ausgeführt.
Dies ist eine Teilmenge des
Liskov Substitution Principle
(LSP), des L derSOLID
Prinzipien.Ein Beispiel in .NET wäre das Codieren mit
IList
anstelle vonList
oderDictionary
, sodass Sie jede Klasse verwenden können, dieIList
austauschbar in Ihrem Code implementiert ist :Ein weiteres Beispiel aus der Basisklassenbibliothek (BCL) ist die
ProviderBase
abstrakte Klasse - dies bietet eine gewisse Infrastruktur und bedeutet ebenso wichtig, dass alle Anbieterimplementierungen austauschbar verwendet werden können, wenn Sie dagegen codieren.quelle
Wenn Sie eine Auto-Klasse in der Combustion-Car-Ära schreiben, besteht eine große Chance, dass Sie oilChange () als Teil dieser Klasse implementieren. Wenn Elektroautos eingeführt werden, sind Sie jedoch in Schwierigkeiten, da für diese Autos kein Ölwechsel und keine Implementierung erforderlich ist.
Die Lösung des Problems besteht darin, eine performMaintenance () - Schnittstelle in der Fahrzeugklasse zu haben und Details in der entsprechenden Implementierung auszublenden. Jeder Fahrzeugtyp würde eine eigene Implementierung für performMaintenance () bereitstellen. Als Besitzer eines Autos müssen Sie sich nur um performMaintenance () kümmern und müssen sich nicht um Anpassungen kümmern, wenn es zu einer ÄNDERUNG kommt.
Zusätzliche Erklärung: Sie sind ein Autobesitzer, der mehrere Autos besitzt. Sie arbeiten den Service aus, den Sie auslagern möchten. In unserem Fall wollen wir die Wartungsarbeiten aller Autos auslagern.
Sie möchten sich nicht darum kümmern, den Fahrzeugtyp dem Dienstanbieter zuzuordnen. Sie geben nur an, wann Sie die Wartung planen und aufrufen möchten. Ein geeignetes Serviceunternehmen sollte einspringen und die Wartungsarbeiten durchführen.
Alternativer Ansatz.
Sie rufen die Arbeit auf und erledigen sie selbst. Hier erledigen Sie die entsprechenden Wartungsarbeiten.
Was ist der Nachteil des 2. Ansatzes? Sie sind möglicherweise nicht der Experte, wenn es darum geht, den besten Weg für die Wartung zu finden. Ihre Aufgabe ist es, das Auto zu fahren und es zu genießen. Nicht im Geschäft zu sein, es aufrechtzuerhalten.
Was ist der Nachteil des ersten Ansatzes? Es gibt den Aufwand, eine Firma usw. zu finden. Wenn Sie keine Mietwagenfirma sind, lohnt sich die Mühe möglicherweise nicht.
quelle
In dieser Aussage geht es um die Kopplung. Ein möglicher Grund für die Verwendung der objektorientierten Programmierung ist die Wiederverwendung. So können Sie beispielsweise Ihren Algorithmus auf zwei zusammenarbeitende Objekte A und B aufteilen. Dies kann nützlich sein, um später einen anderen Algorithmus zu erstellen, der das eine oder andere der beiden Objekte wiederverwenden kann. Wenn diese Objekte jedoch kommunizieren (Nachrichten senden - Aufrufmethoden), erzeugen sie Abhängigkeiten untereinander. Wenn Sie jedoch eines ohne das andere verwenden möchten, müssen Sie angeben, was ein anderes Objekt C für Objekt A tun soll, wenn wir B ersetzen. Diese Beschreibungen werden als Schnittstellen bezeichnet. Dies ermöglicht es Objekt A, unverändert mit verschiedenen Objekten zu kommunizieren, die auf der Schnittstelle beruhen. Die von Ihnen erwähnte Aussage besagt, dass Sie Schnittstellen erstellen und sich auf diese verlassen sollten, wenn Sie einen Teil eines Algorithmus (oder allgemeiner ein Programm) wiederverwenden möchten.
quelle
Wie andere gesagt haben, bedeutet dies, dass Ihr aufrufender Code nur über ein abstraktes übergeordnetes Element Bescheid wissen sollte, NICHT über die eigentliche implementierende Klasse, die die Arbeit erledigt.
Was hilft, dies zu verstehen, ist das WARUM Sie immer auf eine Schnittstelle programmieren sollten. Es gibt viele Gründe, aber zwei der am einfachsten zu erklärenden sind
1) Testen.
Angenommen, ich habe meinen gesamten Datenbankcode in einer Klasse. Wenn mein Programm die konkrete Klasse kennt, kann ich meinen Code nur testen, indem ich ihn wirklich für diese Klasse ausführe. Ich benutze ->, um "Gespräche mit" zu bedeuten.
WorkerClass -> DALClass Fügen wir dem Mix jedoch eine Schnittstelle hinzu.
WorkerClass -> IDAL -> DALClass.
Die DALClass implementiert also die IDAL-Schnittstelle, und die Worker-Klasse ruft NUR diese auf.
Wenn wir nun Tests für den Code schreiben möchten, können wir stattdessen eine einfache Klasse erstellen, die sich nur wie eine Datenbank verhält.
WorkerClass -> IDAL -> IFakeDAL.
2) Wiederverwendung
Nehmen wir an, wir möchten nach dem obigen Beispiel von SQL Server (den unsere konkrete DALClass verwendet) zu MonogoDB wechseln. Dies würde große Arbeit erfordern, aber NICHT, wenn wir auf eine Schnittstelle programmiert haben. In diesem Fall schreiben wir einfach die neue DB-Klasse und ändern (über die Factory)
WorkerClass -> IDAL -> DALClass
zu
WorkerClass -> IDAL -> MongoDBClass
quelle
Schnittstellen beschreiben Fähigkeiten. Sprechen Sie beim Schreiben von imperativem Code über die von Ihnen verwendeten Funktionen und nicht über bestimmte Typen oder Klassen.
quelle