Verwendet Java instanceOf kompatibel mit dem Design-Prinzip "Programm zu einer Schnittstelle"?

8

Wie Sie wissen, bevorzugt das Design-Prinzip "Programm zu einer Schnittstelle" weitgehend Supertypen statt konkreter Typen oder Implementierungen.

Stimmt es mit dem Prinzip überein, instanceof in einem Java-Programm zu verwenden, um einen konkreten Typ aus einem Supertyp abzuleiten?

In meiner Anwendung ist Storehouse eine abstrakte Supertype-Klasse mit einigen privaten Variablen und öffentlichen Gettern und Setter.

ConcreteStorehouseA erbt von Storehouse und hat viele konkrete Methoden und Variablen. ConcreteStorehouseB ist ähnlich, aber anders.

Meine Bewerbung erhält ein Storehouse. Storehouse ist jedoch kein nützlicher Typ zum Arbeiten. Da die einzigen wirklich nützlichen Methoden in den konkreten Typen enthalten sind, verwende ich instanceof wie folgt:

%Vor%

Ist instanceof kompatibel mit dem Prinzip?

Bearbeiten:

Im Wesentlichen ist die Anwendung ein Würfel-Simulator für ein Table-Top-RPG, Shadowrun. Die konkreten Typen sind die verschiedenen Testtypen - Success Test, Opposed Test, Extended Test - die alle sehr unterschiedliche Faktoren und Parameter für ihren erfolgreichen Betrieb haben. Der Supertyp enthält im Wesentlichen den Würfelpool!

    
Arvanem 11.02.2011, 21:20
quelle

7 Antworten

10

Als Faustregel gilt, dass das von Ihnen erwähnte "Programm zu Schnittstellen" -Prinzip übersetzt werden kann in: import nur der Schnittstellentyp, keine Kompilierungszeitabhängigkeit von Unterklassen .

Daher wäre die Antwort auf Ihre Frage definitiv nein. Sie programmieren nicht auf Schnittstellen, da Sie in konkrete Typen umgewandelt haben.

    
Costi Ciudatu 11.02.2011, 21:26
quelle
8

Sie haben es selbst gesagt:

  

Meine Bewerbung erhält ein Storehouse. Storehouse ist jedoch kein nützlicher Typ zum Arbeiten. Weil die einzigen wirklich nützlichen Methoden in den konkreten Typen enthalten sind

Mit anderen Worten, deine Storehouse Abstraktion kauft dir nichts ... warum hast du sie?

Könnten Sie abstrakte Methoden in Storehouse , die in jeder konkreten Klasse implementiert sind, erstellen, damit Sie dann die konkreten Typen auf die gleiche Weise in Ihrem Client-Code behandeln können? Das ist das Ziel der Abstraktion.

    
Jon Skeet 11.02.2011 21:23
quelle
2

Nicht wirklich. Wenn Ihre Methode abhängig von dem Typ, den sie empfängt, ein völlig anderes Verhalten aufweist, dann kauft Ihnen der Polymorphismus nichts. Sie sollten zwei separate überladene Methoden in Betracht ziehen, von denen eine ConcreteStorehouseA als Argument und die andere ein ConcreteStorehouseB verwendet.

    
Oliver Charlesworth 11.02.2011 21:25
quelle
2

Es ist nicht immer eine Sünde. Angenommen, Sie implementieren eine Spezifikation, die besagt, wenn x A ist, dann tue dies, andernfalls, wenn x Y ist, tue das. Es ist besser, wenn Ihr Code wie die Spezifikation aussieht. Es künstlich in kleine Stücke zu zerlegen und in unterschiedliche Quellen zu stellen, ist nicht nur protzig, sondern auch kompliziert, unsicher, schwer zu verstehen und schwer zu pflegen.

Programmierprobleme sind mehrdimensional. Programmiersprachen sind eindimensional, zumindest für den Moment. Es ist eine Kunst, verwandte Themen genau zu organisieren. Kauft nicht in das Dogma ein, dass Bedenken nach Klassen zerlegt werden müssen, dann kann eine Sorge höchstens auf eine Klasse verweisen, und sie muss innerhalb dieser Klasse liegen.

Im vergangenen Jahrhundert gab es dieses großartige Tabu in der Softwareentwicklung, laut den Experten, die wussten, wie man bessere Software schreibt: Codewechsel sollte um jeden Preis vermieden werden. Wenn Sie irgendeinen Quellcode, den Sie vorher geschrieben haben, ändern, könnte das Universum jederzeit in eine Erdnuss zerfallen. Sie können also von Anfang an eine perfekte Architektur entwerfen und dann jede Anforderung ändern, indem Sie eine neue Klasse / clean hinzufügen, ohne die vorhandene Codebasis zu berühren.

Das war, lassen Sie mich hier sehr genau schreiben, totaler Unsinn , schon damals.

Heute haben wir viel bessere Tools, und Code-Änderungen sind nicht nur sicher, sondern sogar erwünscht. Die beste Möglichkeit, Code-Änderungen morgen aus unvorhersehbaren Gründen zu vereinfachen, besteht darin, den Code so einfach wie möglich zu halten. Schreibe Code in einer Weise, die du sogar in einem Komma verstehen kannst.

    
irreputable 11.02.2011 22:35
quelle
1

Es kann schwierig sein, sicher zu sein, ohne zu wissen, welche Operationen Sie ausführen, aber ein eleganteres Design wäre, dass StoreHouse Methodensignaturen für die verschiedenen "Operationen" definiert. Dann führen Sie anstelle der if (instanceof) Prüfungen nur die Operationen aus, und die concreteStorehouses würden diese Operationen implementieren.

%Vor%

In Ihrem Anrufcode anstelle von:

%Vor%

Sie können dann Polymorphie verwenden, um die Operationen auszuführen, ohne sich darum zu kümmern, welche Implementierung ausgeführt wird.

%Vor%

wo concreteStorehouseA und ConcreteStorehouseB Implementierungen für diese Operationen definiert haben.

    
philippe 11.02.2011 21:29
quelle
1

Es klingt, als wäre die Storehouse Abstraktion in diesem Fall überhaupt keine richtige Abstraktion. Als ein Typ an sich ist es nicht wirklich etwas für Sie.

Eine Sache, die helfen kann, ist, zu versuchen, Ihre Implementierungen überhaupt nicht als "Typen" zu betrachten. Der "Typ" ist die Abstraktion, die die Klasse implementiert. (Ziehen Sie im Allgemeinen die Begriffe "Klasse" und "Typ" auseinander.) Der Typ, mit dem Sie arbeiten, ist also Storehouse . ConcreteStorehouseA ist ein Storehouse und ebenso ConcreteStorehouseB . Also die Frage wird, was ist ein Storehouse ? Das ist der Typ, der definiert, was jeder ist.

In diesem speziellen Fall klingt es so, als wären die verschiedenen Storehouse -Implementierungen (zumindest in ihrer aktuellen Implementierung) so verschieden, dass sie nicht wirklich eine werthaltige Abstraktion teilen. Der abstrakte "Typ" bietet in diesem Fall nur einige allgemeine Funktionen durch Vererbung, anstatt den Typ tatsächlich zu abstrahieren.

Um es anders auszudrücken, es klingt so, als ob die Storehouse Implementierungen hier ein klassisches Beispiel für das Liskov Substitution Motivationsplakat sind: Ссылка

>     
David 11.02.2011 21:31
quelle
0

Wie verschiedene Leute darauf hingewiesen haben, programmiert dies nicht für die Schnittstelle. Offensichtlich ist die Schnittstellenabstraktion für Ihre Anforderungen zu schwach.

Es gibt verschiedene Möglichkeiten, damit umzugehen, darunter:

  • Wenn die Schnittstelle unter Ihrer Kontrolle steht, können Sie sie erweitern. Überlege, ob es das wert ist, es könnte ein zu hoher Preis sein, besonders wenn der nächste Aufzählungspunkt gilt.
  • Wenn Sie nur eine Art von Betonlager verwenden, können Sie diese direkt verwenden.
  • Wenn Sie verschiedene Arten von Warehouses unterstützen müssen, ist es eine gute Alternative, Ihr eigenes Interface zu definieren, das genau die Abstraktion liefert, die Sie benötigen, und einen dünnen Wrapper für jede Art konkreter Klasse (Adaptermuster) zu schreiben.
Barend 11.02.2011 21:31
quelle