Estoy siguiendo esta pregunta , pero estoy cambiando mi enfoque del código a un principio.
Desde mi entendimiento del principio de sustitución de Liskov (LSP), cualquier método que esté en mi clase base, debe implementarse en mi subclase, y de acuerdo con esta página, si anula un método en la clase base y no hace nada o arroja un excepción, estás violando el principio.
Ahora, mi problema puede resumirse así: tengo un resumen Weapon class, y dos clases, Swordy Reloadable. Si Reloadablecontiene un específico method, llamado Reload(), tendría que bajar para acceder a eso method, e idealmente, querrás evitarlo.
Entonces pensé en usar el Strategy Pattern. De esta manera, cada arma solo era consciente de las acciones que es capaz de realizar, por lo que, por ejemplo, un Reloadablearma, obviamente, puede recargarse, pero Swordno puede, y ni siquiera es consciente de a Reload class/method. Como dije en mi publicación de Stack Overflow, no tengo que abatir y puedo mantener una List<Weapon>colección.
En otro foro , la primera respuesta sugerida Swordpara ser consciente Reload, simplemente no haga nada. Esta misma respuesta se dio en la página de desbordamiento de pila a la que he vinculado anteriormente.
No entiendo completamente por qué. ¿Por qué violar el principio y permitir que Sword sea consciente Reloady dejarlo en blanco? Como dije en mi publicación Stack Overflow, el SP resolvió mis problemas.
¿Por qué no es una solución viable?
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) ;
}
}
Interfaz de ataque e implementación:
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()blanco o si standardActionsno contiene una acción de recarga es solo un mecanismo diferente. No hay diferencia fundamental. Puedes hacer las dos cosas. => Su solución es viable (que era su pregunta) .; Sword no necesita saber sobre la recarga si Arma contiene una implementación predeterminada en blanco.
class Weapon { bool supportsReload(); void reload(); }. Los clientes probarían si son compatibles antes de volver a cargar.reloadse define contractualmente para lanzar iff!supportsReload(). Eso se adhiere al LSP si las clases derivadas se adhieren al protocolo que acabo de describir.