Sicher, aber wir nennen das Zusammensetzung und Delegation . Das Strategiemuster und die Abhängigkeitsinjektion mögen strukturell ähnlich erscheinen, aber ihre Absichten sind unterschiedlich.
Das Strategiemuster ermöglicht eine Laufzeitänderung des Verhaltens unter derselben Schnittstelle. Ich konnte einer Stockente sagen, sie solle fliegen und sie mit Flügeln fliegen sehen. Tauschen Sie es dann gegen eine Jet-Pilot-Ente aus und beobachten Sie, wie es mit Delta Airlines fliegt. Dies zu tun, während das Programm ausgeführt wird, ist eine Strategie-Muster-Sache.
Die Abhängigkeitsinjektion ist eine Technik zur Vermeidung von Abhängigkeiten bei der harten Codierung, sodass sie unabhängig voneinander geändert werden können, ohne dass Clients bei Änderungen geändert werden müssen. Kunden drücken einfach ihre Bedürfnisse aus, ohne zu wissen, wie sie erfüllt werden. Daher wird an anderer Stelle (in der Regel hauptsächlich) entschieden, wie sie erfüllt werden. Sie brauchen keine zwei Enten, um diese Technik anzuwenden. Nur etwas, das eine Ente benutzt, ohne zu wissen oder sich darum zu kümmern, welche Ente. Etwas, das die Ente nicht baut oder danach sucht, aber vollkommen glücklich ist, die Ente zu verwenden, die Sie ihr geben.
Wenn ich eine konkrete Entenklasse habe, kann ich sie das Flugverhalten implementieren lassen. Ich könnte sogar das Verhalten von Fly-with-Wings auf Fly-with-Delta basierend auf einer Zustandsvariablen ändern lassen. Diese Variable kann ein Boolescher Wert, ein Int oder FlyBehavior
eine fly
Methode sein , die eine Methode hat, die jeden Flugstil ausführt, ohne dass ich sie mit einem if testen muss. Jetzt kann ich den Flugstil ändern, ohne den Ententyp zu ändern. Jetzt können Stockenten Piloten werden. Dies ist Zusammensetzung und Delegation . Die Ente besteht aus einem FlyBehavior und kann Fluganfragen an sie delegieren. Auf diese Weise können Sie alle Verhaltensweisen Ihrer Enten auf einmal ersetzen oder für jedes Verhalten oder eine beliebige Kombination dazwischen etwas halten.
Dies gibt Ihnen alle die gleichen Kräfte, die die Vererbung außer einer hat. Mit der Vererbung können Sie ausdrücken, welche Duck-Methoden Sie in den Duck-Subtypen überschreiben. Für die Komposition und Delegierung muss die Ente von Anfang an explizit an Subtypen delegieren. Dies ist weitaus flexibler, erfordert jedoch mehr Tastatureingaben und Duck muss wissen, dass dies geschieht.
Viele Menschen glauben jedoch, dass die Vererbung von Anfang an explizit ausgelegt werden muss. Und wenn dies nicht der Fall ist, sollten Sie Ihre Klassen als versiegelt / endgültig markieren, um die Vererbung zu verbieten. Wenn Sie diese Ansicht vertreten, hat die Vererbung keinen Vorteil gegenüber der Zusammensetzung und Delegierung. Denn dann muss man so oder so entweder von Anfang an auf Erweiterbarkeit ausgelegt sein oder bereit sein, Dinge später abzureißen.
Abreißen ist eigentlich eine beliebte Option. Seien Sie sich nur bewusst, dass es Fälle gibt, in denen es ein Problem gibt. Wenn Sie Bibliotheken oder Codemodule unabhängig voneinander bereitgestellt haben, die Sie mit der nächsten Version nicht aktualisieren möchten, kann es sein, dass Sie nicht mehr mit Versionen von Klassen zu tun haben, die nichts über Ihre aktuellen Aktivitäten wissen.
Die Bereitschaft, Dinge später abzureißen, kann Sie von übermäßigem Entwerfen befreien. Es ist jedoch sehr mächtig, etwas zu entwerfen, das eine Ente verwendet, ohne wissen zu müssen, was die Ente tatsächlich tun wird, wenn sie verwendet wird. Das Nichtwissen ist mächtiges Zeug. So können Sie für eine Weile aufhören, an Enten zu denken, und über den Rest Ihres Codes nachdenken.
"Können wir" und "sollten wir" sind unterschiedliche Fragen. Die Komposition gegenüber der Vererbung zu bevorzugen bedeutet nicht, niemals die Vererbung zu verwenden. Es gibt immer noch Fälle, in denen Vererbung am sinnvollsten ist. Ich zeige Ihnen mein Lieblingsbeispiel :
public class LoginFailure : System.ApplicationException {}
Mit der Vererbung können Sie Ausnahmen mit spezifischeren, beschreibenden Namen in nur einer Zeile erstellen.
Versuchen Sie das mit Komposition und Sie werden ein Chaos bekommen. Es besteht auch kein Risiko für das Vererbungs- Jojo-Problem, da hier keine Daten oder Methoden zur Wiederverwendung und Förderung der Vererbungsverkettung vorhanden sind. Das alles fügt einen guten Namen hinzu. Unterschätze niemals den Wert eines guten Namens.
Duckbehavior.quackBehavior
und andere Felder enthält Ihr Code?