Я предпочитаю разделить этот logi c на три разных интерфейса:
public interface IWeapon {} //deals damage
public interface IArmor {} //reduces damage
public interface IBuff {} //modifies entire plot into something else, for example, swapping armor/damage, or identifiyng damage type, or deal/heal damage, or make some special effect like burning, frozen, chilled, etc. Or just specifying you fighting on EXTREME HARDCORE, thus reducing your armor to nothing.
Затем я бы определил интерфейс, который вычисляет, что происходит при ударе:
public interface IDamage {} //identifies what happens, it can deal zero damage and flip player upside down, froze him, or whatever.
public inteface IDamageSystem
{
IDamage Calculate(IWeapon weapon, IArmor armor, params IBuff[] buffs);
}
В идеале, IWeapon / IArmor сам по себе является баффом, поэтому его можно опустить, вы просто передаете кучу условий и соответственно рассчитываете урон.
Тогда что-то вроде apply должно присутствовать на ваших "здоровых" объектах, что в конечном итоге просто изменяет состояние сущность и ничего больше:
public interface ILivingBeing
{
void ApplyDamage(IDamage damage);
}