Ich habe ein konzeptionelles Problem mit einer ordnungsgemäßen Implementierung von Code, die scheinbar eine Mehrfachvererbung erfordert. Dies wäre in vielen OO-Sprachen kein Problem, aber da das Projekt für Android ist, gibt es keine Mehrfachvererbung extends
.
Ich habe eine Reihe von Aktivitäten, die von verschiedenen Basisklassen abgeleitet ist , wie einfach Activity
, TabActivity
, ListActivity
, ExpandableListActivity
, etc. Auch habe ich einige Code - Fragmente , die ich Platz brauche in onStart
, onStop
, onSaveInstanceState
, onRestoreInstanceState
und anderen Standard - Event - Handler in allen Aktivitäten.
Wenn ich für alle Aktivitäten eine einzige Basisklasse habe, platziere ich den Code in einer speziellen abgeleiteten Zwischenklasse und erstelle dann alle Aktivitäten, mit denen er erweitert wird. Dies ist leider nicht der Fall, da es mehrere Basisklassen gibt. Aber die gleichen Teile des Codes in mehrere Zwischenklassen einzuteilen, ist kein Weg, imho.
Ein anderer Ansatz könnte darin bestehen, ein Helferobjekt zu erstellen und alle Aufrufe der oben genannten Ereignisse an den Helfer zu delegieren. Dies erfordert jedoch, dass das Hilfsobjekt eingeschlossen und alle Handler in allen Zwischenklassen neu definiert werden. Es gibt also keinen großen Unterschied zum ersten Ansatz hier - immer noch viele Code-Duplikate.
Wenn eine ähnliche Situation unter Windows auftritt, würde ich die Basisklasse (etwas, das der Activity
Klasse in Android "entspricht") in Unterklassen unterteilen und entsprechende Nachrichten dort abfangen (an einem einzigen Ort).
Was kann man in Java / Android dafür tun? Ich weiß, dass es interessante Tools wie Java-Instrumentierung gibt ( mit einigen echten Beispielen ), aber ich bin kein Java-Guru und nicht sicher, ob es sich lohnt, es in diesem speziellen Fall zu versuchen.
Wenn ich andere anständige Lösungen verpasst habe, erwähnen Sie sie bitte.
AKTUALISIEREN:
Für diejenigen, die das gleiche Problem in Android lösen möchten, habe ich eine einfache Lösung gefunden. Es gibt die Application- Klasse, die unter anderem das Interface ActivityLifecycleCallbacks bereitstellt . Es tut genau das, was ich brauche, damit wir wichtige Ereignisse für alle Aktivitäten abfangen und aufwerten können. Der einzige Nachteil dieser Methode ist, dass sie ab API-Level 14 verfügbar ist, was in vielen Fällen nicht ausreicht (die Unterstützung von API-Level 10 ist heutzutage eine typische Anforderung).
decordator pattern
. Dies ist ein letzter Ausweg, der tatsächlich zeigt, was ich lieber vermeiden würde - Code-Duplizierung. Ich nehme Ihre Antwort an, wenn keine anderen Ideen auftauchen. Kann ich möglicherweise Generika verwenden, um den Code der "Intermediates" zu verallgemeinern?Ich denke, Sie versuchen, die falsche Art der Code-Duplizierung zu vermeiden. Ich glaube, Michael Feathers hat einen Artikel darüber geschrieben, aber ich kann ihn leider nicht finden. So wie er es beschreibt, können Sie sich Ihren Code als zweiteilig wie eine Orange vorstellen: Die Schale und das Fruchtfleisch. Die Rinde ist das Zeug wie Methodendeklarationen, Felddeklarationen, Klassendeklarationen usw. Das Fruchtfleisch ist das Zeug in diesen Methoden; die Umsetzung.
Wenn es um TROCKEN geht, möchten Sie vermeiden, Zellstoff zu duplizieren . Aber oft entsteht dabei mehr Rinde. Und das ist in Ordnung.
Hier ist ein Beispiel:
Dies kann folgendermaßen überarbeitet werden:
Bei diesem Refactoring haben wir viel Schwarte hinzugefügt. Das zweite Beispiel weist jedoch eine wesentlich sauberere Darstellung
method()
mit weniger DRY-Verstößen auf.Sie sagten, Sie möchten das Dekorationsmuster vermeiden , da es zu einer Codeduplizierung führt. Wenn Sie sich das Bild in diesem Link ansehen, werden Sie feststellen, dass es nur die
operation()
Signatur (dh die Rinde) dupliziert . Dieoperation()
Implementierung (Zellstoff) sollte für jede Klasse unterschiedlich sein. Ich denke, Ihr Code wird dadurch sauberer und hat weniger Zellstoffduplikationen.quelle
Sie sollten die Komposition der Vererbung vorziehen. Ein schönes Beispiel ist das IExtension " pattern " im .NET WCF Framework. Baiscally haben Sie 3 Schnittstellen, IExtension, IExtensibleObject und IExtensionCollection. Anschließend können Sie komponieren die unterschiedlichen Verhaltensweisen von addig IExtension Instanzen es die Erweiterung IExtensionCollection Eigenschaft mit einem IExtensibleObject Objekt. In Java sollte es ungefähr so aussehen, aber Sie müssen keine eigene IExtensioncollection-Implementierung erstellen, die die Methoden attach und detach aufruft, wenn Elemente hinzugefügt / entfernt werden. Beachten Sie auch, dass Sie die Erweiterungspunkte in Ihrer erweiterbaren Klasse definieren müssen. Im Beispiel wird ein ereignisähnlicher Rückrufmechanismus verwendet:
Dieser Ansatz bietet den Vorteil der Wiederverwendung von Erweiterungen, wenn Sie es schaffen, gemeinsame Erweiterungspunkte zwischen Ihren Klassen zu extrahieren.
quelle
processor.addHandler(console)
vorausgesetzt, dassConsoleProcessor
die Callback-Schnittstelle selbst implementiert. Das "Erweiterungsmuster" sieht aus wie ein Mix ausvisitor
unddecorator
, aber ist es in diesem Fall notwendig?Ab Android 3.0 kann dies möglicherweise mithilfe eines Fragments elegant gelöst werden . Fragmente haben ihre eigenen Rückrufe für den Lebenszyklus und können in eine Aktivität eingefügt werden. Ich bin mir jedoch nicht sicher, ob dies bei allen Veranstaltungen funktionieren wird.
Eine weitere Option , die ich auch bin nicht sicher (fehlt in eingehender Android Know-how) könnte einen Decorator in entgegengesetzter Weise k3b zu benutzen , schlägt vor: ein erstellen ,
ActivityWrapper
deren Callback - Methoden enthalten Ihren gemeinsamen Code und dann nach vorne zu einem gewickeltenActivity
Gegenstand (Ihr tatsächlichen Implementierungsklassen), und lassen Sie dann Android diesen Wrapper starten.quelle
Es ist wahr, dass Java Mehrfachvererbung nicht zulässt, aber Sie können es mehr oder weniger simulieren, indem Sie dafür sorgen, dass jede Ihrer SomeActivity-Unterklassen die ursprüngliche Activity-Klasse erweitert.
Sie werden etwas haben wie:
quelle