Was Sie beschreiben, ist perfekt möglich und allgemein bekannt als "Decorator Pattern".
Link-Only-Antworten sind schlecht, ich werde später erarbeiten, wenn ich mehr Zeit habe.
Unterdessen hat Wikipedia mehr Info: Decorator Pattern.
1 Cat cat = new Cat();
2 Animal pet = new Pet(cat, "Foo");
3 if (pet instanceof Pet){
4 if (pet.kind instanceof Cat){
5 Pet.sayMeow();
6 }
7 }
Dies hat den Nachteil, dass Sie instanceOf
verwenden müssen. Normalerweise würden Sie Ihre Animal
Klasse eine Methode haben - nennen wir es makeNoise
. Wahrscheinlich abstrakt. Sie Tier-Implementierungen (Cat
, Dog
...) würde dann diese Methode überschreiben, um ihr entsprechendes Geräusch ("Bark", "Miow" ...) zu machen.
In dem Ausschnitt scheint es, dass nur Haustiere Geräusche machen können ... das macht es ein bisschen komplizierter, weil es verschiedene Möglichkeiten gäbe, dies zu tun.
Sie könnten den Dekorator einen Ton speichern lassen und das makeNoise überschreiben, um diesen Ton zu erzeugen. Wie so:
Cat catInstance = new Cat();
catInstance.makeNoise(); // Default impl: NOP => "" - no sound.
Animal pet = new Pet(catInstance, "Mieow");
pet.makeNoise(); // => "Mieow"
Der Punkt, der all dies ist: Sie wollen mit instanceof
vermeiden. Es ist dir egal, ob das Tier eine Katze, ein Hund, eine Haustier-Katze oder ein Haustier-Hund ist. Sie müssen ihre korrekten Töne machen, wenn und wenn sie dazu aufgefordert werden. Also könntest du eine Sammlung von "Tier" s haben und sie alle an "makeNoise" erzählen und jeder wird still bleiben, bellen oder sich umschauen, ohne dass du dich darum kümmern musst, ob es Haustiere sind oder welches spezielle Kind von Animal
.
BEARBEITEN: Lesen meine Antwort wieder, es ist eher wie eine Politik (Strategie Muster) als ein Dekorateur. Die Richtlinie ändert, wie etwas ausgeführt wird, während der Dekorator die Funktion hinzufügen würde.
Also ein echter Dekorator zu sein, würde bedeuten, dass makeNoise
in der Schnittstelle von Pet
wäre. Was bedeutet, dass Sie diese Methode nicht bei Animals aufrufen können.
Deshalb ändere ich meinen Vorschlag von "Decorator" zu "Strategy" Muster.
Das obige Beispiel gilt immer noch. Sie haben eine "Standard" -Strategie und injizieren die "Pet" -Strategie mit einem Decorator-ähnlichen Implementierungsansatz.
Natürlich könnte das alles auch anders gemacht werden, um das Muster strenger zu implementieren.
Endlich klingelt if(x instanceof X) ...
immer noch die "Visitor" -Bell, auch.
Fragen Sie sich: Was soll 'Pet' mit dem übergebenen' Tier' machen? Sie tun derzeit nichts damit, deshalb ist diese Frage unklar (unklar, was Ihr Grund für die Übergabe von "Tier" ist). – Tom
Was @Tom sagte: einige weitere Informationen über das, was Sie erreichen möchten, wären nett. Momentan klingt das nach etwas, für das man eine 'Schnittstelle' verwenden könnte. – domsson
Wenn Sie sagen, dass Sie eine vorhandene Instanz von "Animal" verwenden und diese Instanz ** rückwirkend in ein "Pet" konvertieren möchten, können Sie das nicht tun. Sie können ein neues "Pet" erstellen, das von einer "Animal" -Instanz initialisiert wird, aber es wird separat sein. Die Klasse einer Instanz ist beim Erstellen gesperrt. (Wir können verschiedene Ansichten von [interfaces to] dieser Instanz haben, einige Code wissen vielleicht nur, dass es ein 'Animal' ist und anderer Code kann wissen, dass es ein' Cat' ist, aber die * instance * hat eine bestimmte Klasse, wenn sie erstellt wird.) –