Я занимаюсь этим вопросом , но переключаюсь с кода на принцип.
Исходя из моего понимания принципа подстановки Лискова (LSP), какие бы методы ни находились в моем базовом классе, они должны быть реализованы в моем подклассе, и, согласно этой странице, если вы переопределяете метод в базовом классе и он ничего не делает или выдает исключение, вы нарушаете принцип.
Теперь моя проблема может быть подытожена так: у меня есть реферат Weapon
class
, два класса Sword
и Reloadable
. Если Reloadable
содержит конкретный method
, вызываемый Reload()
, я должен был бы понизить доступ к нему method
, и, в идеале, вы бы хотели этого избежать.
Затем я подумал об использовании Strategy Pattern
. Таким образом, каждое оружие было осведомлено только о действиях, которые оно может выполнить, так что, например, Reloadable
оружие может перезаряжаться, но Sword
не может и даже не знает о Reload class/method
. Как я уже говорил в своем сообщении о переполнении стека, мне не нужно унывать, и я могу поддерживать List<Weapon>
коллекцию.
На другом форуме первый ответ предложил дать Sword
знать Reload
, просто ничего не делать. Этот же ответ был дан на странице переполнения стека, на которую я ссылался выше.
Я не до конца понимаю почему. Зачем нарушать принцип и позволять Мечу быть в курсе Reload
и оставлять его пустым? Как я сказал в своем посте переполнения стека, SP, в значительной степени решил мои проблемы.
Почему это не жизнеспособное решение?
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) ;
}
}
Интерфейс атаки и реализация:
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()
пустым или standardActions
нет действия перезагрузки - это просто другой механизм. Там нет принципиальной разницы. Вы можете сделать оба. => Ваше решение является жизнеспособным (это был ваш вопрос) .; Sword не нужно знать о перезагрузке, если Weapon содержит пустую реализацию по умолчанию.
class Weapon { bool supportsReload(); void reload(); }
. Клиенты будут проверять, если поддерживается, до перезагрузки.reload
определяется контрактом бросить тогда и только тогда!supportsReload()
. Это придерживается LSP, если классы вождения придерживаются протокола, который я только что обрисовал.