Betrachten wir zwei Klassen Dog
und Cat
konform sowohl zu Animal
Protokoll (in Bezug auf die Swift - Programmiersprache. Diese Schnittstelle in Java / C # würde).
Wir haben einen Bildschirm mit einer gemischten Liste von Hunden und Katzen. Es gibt eine Interactor
Klasse, die hinter den Kulissen mit Logik umgeht.
Jetzt möchten wir dem Benutzer eine Bestätigungsbenachrichtigung anzeigen, wenn er eine Katze löschen möchte. Hunde müssen jedoch sofort ohne Benachrichtigung gelöscht werden. Die Methode mit Bedingungen würde folgendermaßen aussehen:
func tryToDeleteModel(model: Animal) {
if let model = model as? Cat {
tellSceneToShowConfirmationAlert()
} else if let model = model as? Dog {
deleteModel(model: model)
}
}
Wie kann dieser Code überarbeitet werden? Es riecht offensichtlich
quelle
Dog
undCat
werden als Klassen beschrieben, währendAnimal
es sich um ein Protokoll handelt, das von jeder dieser Klassen implementiert wird. Es besteht also ein gewisses Missverhältnis zwischen der Frage und Ihrer Antwort.Interactor
jetzt vom Zustand abCat
undDog
gehandhabt werden, kann und soll eine gemeinsame Eigenschaft in seinAnimal
. Wenn Sie etwas anderes tun, müssen Sie später nach Wartungsproblemen fragen.Tell vs. Ask
Den bedingten Ansatz, den Sie zeigen, würden wir " fragen " nennen. Hier fragt der konsumierende Kunde : "Was für eine Art sind Sie?" und passt ihr Verhalten und ihre Interaktion mit Objekten entsprechend an.
Dies steht im Gegensatz zu der Alternative, die wir " Tell " nennen. Mit tell schieben Sie mehr Arbeit in die polymorphen Implementierungen, sodass der konsumierende Client-Code einfacher, ohne Bedingungen und unabhängig von den möglichen Implementierungen üblich ist.
Da Sie eine Bestätigungswarnung verwenden möchten, können Sie dies zu einer expliziten Funktion der Schnittstelle machen. Möglicherweise haben Sie eine boolesche Methode, die optional mit dem Benutzer prüft und den booleschen Bestätigungswert zurückgibt. In den Klassen, die nicht bestätigen möchten, überschreiben sie einfach mit
return true;
. Andere Implementierungen bestimmen möglicherweise dynamisch, ob sie eine Bestätigung verwenden möchten.Der konsumierende Client verwendet immer die Bestätigungsmethode, unabhängig von der jeweiligen Unterklasse, mit der er arbeitet. Dadurch wird die Interaktion angezeigt, anstatt zu fragen .
(Ein anderer Ansatz wäre, die Bestätigung in den Löschvorgang zu verschieben. Dies würde jedoch die Kunden überraschen, die erwarten, dass ein Löschvorgang erfolgreich ist.)
quelle
Interactor
jetzt vom Zustand abDie Entscheidung, ob eine Bestätigung erforderlich ist, liegt in der Verantwortung der
Cat
Klasse. Aktivieren Sie sie daher, um diese Aktion auszuführen. Ich kenne Kotlin nicht, also werde ich die Dinge in C # ausdrücken. Hoffentlich sind die Ideen dann auch auf Kotlin übertragbar.Wenn Sie dann eine
Cat
Instanz erstellen , geben Sie diese anTellSceneToShowConfirmationAlert
, die zurückgegeben werden muss,true
wenn OK zum Löschen:Und dann wird Ihre Funktion:
quelle
Cat
Klasse erforderlich ist . Ich würde argumentieren, dass es dort hingehört. Es kann nicht entscheiden, wie diese Bestätigung erreicht wird (die injiziert wird) und es löscht sich nicht von selbst. Nein, die Löschlogik wird nicht in das Modell verschoben.TellSceneToShowConfirmationAlert
in eine Instanz von zu injizierenCat
. In Situationen, in denen dies nicht einfach ist (z. B. in einem mehrschichtigen System, in dem diese Funktionalität auf einer tiefen Ebene liegt), wäre dieser Ansatz nicht gut.Ich würde raten, ein Besuchermuster zu wählen. Ich habe eine kleine Implementierung in Java gemacht. Ich bin nicht mit Swift vertraut, aber Sie können es leicht anpassen.
Der Besucher
Dein Modell
Den Besucher anrufen
Sie können so viele Implementierungen von AnimalVisitor haben, wie Sie möchten.
Beispiel:
quelle