Исправление большого недостатка шаблона декоратора

Некоторое время назад при рефакторинге некоторого боевого кода игры я решил попробовать шаблон декоратора. У бойцов могут быть различные пассивные способности, и они также могут быть разными типами существ. Я подумал, что декоратор позволяет мне добавлять поведение в различных комбинациях во время выполнения, поэтому мне не нужны сотни подклассов.

Я почти закончил делать примерно 15 декораторов для пассивных способностей, и в ходе тестирования я обнаружил кое-что - довольно явный недостаток шаблона декоратора, о котором я удивился, о котором раньше не слышал.

Чтобы декораторы работали вообще, их методы должны быть вызваны на самом внешнем декораторе. Если «базовый класс» - обернутый объект - вызывает один из своих собственных методов, этот метод не будет декорированной перегрузкой, поскольку нет никакого способа для вызова быть "виртуализированным" для вызова; к обертке. Вся концепция искусственного подкласса рушится.

Это своего рода большое дело. У моих бойцов есть такие методы, какTakeHit которые в свою очередь называют своимиDamage метод. Но украшенныйDamage не вызывается вообще.

Возможно, я выбрал неправильный шаблон или переусердствовал в его применении. Есть ли у вас какие-либо советы относительно более подходящей схемы в этой ситуации или способа обойти этот недостаток? В коде, из которого я сделал рефакторинг, все пассивные способности разбросаны по всему боевому коду внутриif блоки в, казалось бы, случайных местах, поэтому я хотел это разложить.

edit: some code
public function TakeHit($attacker, $quality, $damage)
{
    $damage -= $this->DamageReduction($damage);

    $damage = round($damage);

    if ($damage < 1) $damage = 1;

    $this->Damage($damage);

    if ($damage > 0)
    {
        $this->wasHit = true;
    }

    return $damage;
}

Этот метод в основеCombatant учебный класс.DamageReduction а такжеDamage могут и могут быть переопределены в различных декораторах, например пассив, который уменьшает урон на четверть, или другой, который отражает некоторый урон атакующему.

class Logic_Combatant_Metal extends Logic_Combatant_Decorator
{
    public function TakeHit($attacker, $quality, $damage)
    {
        $actual = parent::TakeHit($attacker, $quality, $damage);

        $reflect = $this->MetalReflect($actual);
        if ($reflect > 0)
        {
            Data_Combat_Event::Create(Data_Combat_Event::METAL_REFLECT, $target->ID(), $attacker->ID(), $reflect);
            $attacker->Damage($reflect);
        }

        return $actual;
    }

    private function MetalReflect($damage)
    {
        $reflect = $damage * ((($this->Attunement() / 100) * (METAL_REFLECT_MAX - METAL_REFLECT_MIN)) + METAL_REFLECT_MIN);
        $reflect = ceil($reflect);

        return $reflect;
    }
}

Но опять же, эти методы декоратора никогда не вызываются, потому что они не вызываются извне, они вызываются внутри базового класса.

Ответы на вопрос(2)

Ваш ответ на вопрос