Bu soruyu takip ediyorum , ama odağımı koddan ilkeye geçiriyorum.
Liskov ikame ilkesini (LSP) anladığımdan, temel sınıfımda ne olursa olsun, alt sınıfımda uygulanmaları gerekir ve bu sayfaya göre , temel sınıftaki bir yöntemi geçersiz kılarsanız ve hiçbir şey yapmazsa veya istisna, prensibi ihlal ediyorsunuz.
Şimdi, sorunum şu şekilde özetlenebilir: Bir özetim Weapon
class
ve iki dersim var Sword
ve Reloadable
. Denilen Reloadable
belirli bir içeriğe sahipse method
, buna Reload()
erişmek için mahzun etmem gerekir method
ve ideal olarak bundan kaçınmak istersiniz.
Sonra kullanmayı düşündüm Strategy Pattern
. Bu şekilde, her silah yalnızca gerçekleştirebileceği eylemlerin farkındaydı, örneğin bir Reloadable
silah, açıkça yeniden yüklenebilir, ancak bir Sword
yapamaz ve hatta bir farkında bile değildir Reload class/method
. Stack Overflow yayınımda belirttiğim gibi, mahzun etmek zorunda değilim ve bir List<Weapon>
koleksiyon tutabilirim .
On başka forumda ilk cevap izin önerilen Sword
farkında olmak Reload
sadece bir şey yapmayın. Aynı cevap, yukarıda bağlandığım Yığın Taşması sayfasında da verildi.
Nedenini tam olarak anlamıyorum. Prensibi ihlal edip Kılıç'ın farkında olmasına Reload
ve boş bırakmasına neden izin vermeliyim ? Stack Overflow yayınımda söylediğim gibi, SP, sorunlarımı hemen hemen çözdü.
Neden uygun bir çözüm değil?
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) ;
}
}
Saldırı Arayüzü ve Uygulaması:
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()
Boş bırakıp bırakma veya standardActions
yeniden yükleme eylemi içermeme, sadece farklı bir mekanizmadır. Temel bir fark yok. Her ikisini de yapabilirsiniz. => Sizin çözüm olduğunu (sizin soruydu olan) yaşayabilir .; Silah boş bir varsayılan uygulama içeriyorsa, kılıç yeniden yükleme hakkında bilgi sahibi olmak zorunda değildir.
class Weapon { bool supportsReload(); void reload(); }
. İstemciler yeniden yüklemeden önce desteklenip desteklenmediklerini test ederler.reload
iff atmak için sözleşmeye bağlı olarak tanımlanmıştır!supportsReload()
. Bu LSP iff tahrikli sınıflara uyduğu, az önce özetlediğim protokole bağlı.