Kill()
, with no parameters, seems like you are commanding the ninja to commit suicide. I would define Ninja
to act on other ninjas:
public interface INinja
{
void KillBrutally(INinja otherNinja);
void KillHonorably(INinja otherNinja);
}
Then, raise the level of abstraction from weapon to kill move:
public interface IKillMove
{
void Kill(INinja ninja);
}
and have ninjas support the kill types:
public sealed class Ninja : INinja
{
private readonly IKillMove _brutalKillMove;
private readonly IKillMove _honorableKillMove;
public Ninja(IKillMove brutalKillMove, IKillMove honorableKillMove)
{
_brutalKillMove = brutalKillMove;
_honorableKillMove = honorableKillMove;
}
#region INinja
public void KillBrutally(INinja otherNinja)
{
_brutalKillMove.Kill(otherNinja);
}
public void KillHonorably(INinja otherNinja)
{
_honorableKillMove.Kill(otherNinja);
}
#endregion
}
Now we can worry about weapons:
public interface IWeapon
{
void Attack(INinja ninja);
void Finish(INinja ninja);
}
and kill moves:
public sealed class MoveInKillMove : IKillMove
{
private readonly IWeapon _shortRangeWeapon;
private readonly IWeapon _longRangeWeapon;
public MoveInKillMove(IWeapon shortRangeWeapon, IWeapon longRangeWeapon)
{
_shortRangeWeapon = shortRangeWeapon;
_longRangeWeapon = longRangeWeapon;
}
#region IKillMove
public void Kill(INinja ninja)
{
_longRangeWeapon.Attack(ninja);
_longRangeWeapon.Attack(ninja);
_longRangeWeapon.Attack(ninja);
_shortRangeWeapon.Finish(ninja);
}
#endregion
}
public sealed class FinishingMove : IKillMove
{
private readonly IWeapon _weapon;
public FinishingMove(IWeapon weapon)
{
_weapon = weapon;
}
#region IKillMove
public void Kill(INinja ninja)
{
_weapon.Finish(ninja);
}
#endregion
}
Here is a sample wiring (translate to your IoC container as necessary):
var sword = new Sword();
var ninja = new Ninja(
new MoveInKillMove(sword, new Shuriken()),
new FinishingMove(sword));