Ich verfolge diese Frage , aber ich konzentriere mich von Code auf ein Prinzip.
Nach meinem Verständnis des Liskov-Substitutionsprinzips (LSP) müssen alle Methoden in meiner Basisklasse in meiner Unterklasse implementiert werden, und laut dieser Seite, wenn Sie eine Methode in der Basisklasse überschreiben und sie nichts tut oder eine auslöst Ausnahme, Sie verstoßen gegen das Prinzip.
Nun kann mein Problem folgendermaßen zusammengefasst werden: Ich habe eine Zusammenfassung Weapon
class
und zwei Klassen Sword
und Reloadable
. Wenn es Reloadable
ein bestimmtes method
, genanntes Reload()
Element enthält , müsste ich einen Downcast durchführen, um darauf zuzugreifen method
, und im Idealfall möchten Sie dies vermeiden.
Ich dachte dann daran, das zu benutzen Strategy Pattern
. Auf diese Weise war sich jede Waffe nur der Aktionen bewusst, die sie ausführen kann, so dass beispielsweise eine Reloadable
Waffe offensichtlich nachladen kann, aber eine Sword
nicht und nicht einmal eine Reload class/method
. Wie ich in meinem Beitrag zum Stapelüberlauf angegeben habe, muss ich keinen Downcast durchführen und kann eine List<Weapon>
Sammlung verwalten.
In einem anderen Forum schlug die erste Antwort vor, Sword
sich bewusst zu sein Reload
, einfach nichts zu tun. Dieselbe Antwort wurde auf der Seite "Stapelüberlauf" gegeben, auf die ich oben verlinkt habe.
Ich verstehe nicht ganz warum. Warum gegen das Prinzip verstoßen und Sword erlauben, sich dessen bewusst zu sein Reload
und es leer zu lassen? Wie ich in meinem Beitrag zum Stapelüberlauf sagte, hat der SP meine Probleme so ziemlich gelöst.
Warum ist es keine praktikable Lösung?
public final Weapon{
private final String name;
private final int damage;
private final List<AttackStrategy> validactions;
private final List<Actions> standardActions;
private Weapon(String name, int damage, List<AttackStrategy> standardActions, List<Actions> attacks)
{
this.name = name;
this.damage = damage;
standardActions = new ArrayList<Actions>(standardActions);
validAttacks = new ArrayList<AttackStrategy>(validActions);
}
public void standardAction(String action){} // -- Can call reload or aim here.
public int attack(String action){} // - Call any actions that are attacks.
public static Weapon Sword(String name, damage, List<AttackStrategy> standardActions, List<Actions> attacks){
return new Weapon(name, damage,standardActions, attacks) ;
}
}
Angriffsschnittstelle und Implementierung:
public interface AttackStrategy{
void attack(Enemy enemy);
}
public class Shoot implements AttackStrategy {
public void attack(Enemy enemy){
//code to shoot
}
}
public class Strike implements AttackStrategy {
public void attack(Enemy enemy){
//code to strike
}
}
reload()
leer lassen oder standardActions
keine Reload-Aktion enthalten, ist nur ein anderer Mechanismus. Es gibt keinen grundsätzlichen Unterschied. Sie können beides tun. => Ihre Lösung ist realisierbar (was Ihre Frage war).; Sword muss nichts über das Nachladen wissen, wenn Weapon eine leere Standardimplementierung enthält.
class Weapon { bool supportsReload(); void reload(); }
. Clients würden vor dem erneuten Laden testen, ob dies unterstützt wird.reload
wird vertraglich definiert, um iff zu werfen!supportsReload()
. Das entspricht dem LSP, wenn getriebene Klassen dem gerade beschriebenen Protokoll entsprechen.