oop — ОО-дизайн в Декорировании родительского объекта с неизвестными типами потомков

В настоящее время я работаю над системой, в которой объекты анимируются по кривой Безье. В различных, определенных пользователем точках на кривой, может возникнуть событие, на которое должен реагировать анимирующий объект. Это может быть изменение скорости, изменение анимации, изменение направления движения и т. Д.

Пока у меня есть следующий класс AnimationEvent.

class AnimationEvent
{
private:
unsigned int    m_eventID;

float   m_InteroplationPoint;

float   m_SpeedInMPS;

public:
AnimationEvent(unsigned int id, float interpolationPoint);
~AnimationEvent(void);

const unsigned int getEventID();
void setInterpolationPoint(float interpPoint);
const float getInterpPoint();

const float getSpeed();
};

Каждое событие назначается как объект вдоль кривой, и когда достигается точка его интерполяции, класс кривой вызывает getSpeed() функция для изменения текущей скорости анимации.

Что я действительно хочу сделать, так это реализовать систему, например, с помощью шаблона проектирования Decorator, в котором событие может быть украшено несколькими объектами, и когда оно будет достигнуто, будут применены все украшения. У меня проблема в том, что я не могу передать указатель на родительский объект дочернему элементу, так как это создаст циклическую зависимость, но у меня также есть проблема, когда я не знаю (при компиляции), какой тип действий событие будет украшено.

Любые идеи о том, как преодолеть это, будет принята с благодарностью! Если я забыл какую-либо информацию, которая может помочь, я постараюсь отредактировать ее.

1

Решение

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

#include <iostream>
#include <vector>
using namespace std;

class Animatee;
class AnimateEvent
{
public:
virtual Animatee & perform(Animatee & on) = 0;
};

class Animatee
{
public:
Animatee() : value(0){};

void addEvent(AnimateEvent * event)
{
if(event != NULL)
{
events.push_back(event);
}

}

Animatee & act()
{
for(vector<AnimateEvent * >::iterator it = events.begin(); it != events.end();++it)
{
AnimateEvent * event = *it;
event->perform(*this);
}

return *this;
}

double value;   //don't do this, but something more encap'ed
private:

vector<AnimateEvent * > events;
};

class Add : public AnimateEvent
{
virtual Animatee & perform(Animatee & on)
{
on.value = on.value + 1;
return on;
}
};

class Subtract : public AnimateEvent
{
virtual Animatee & perform(Animatee & on)
{
on.value = on.value - 1;
return on;
}
};

class Multiply : public AnimateEvent
{
virtual Animatee & perform(Animatee & on)
{
on.value = on.value * 2;
return on;
}
};

class Div : public AnimateEvent
{
virtual Animatee & perform(Animatee & on)
{
on.value = on.value / 2.0;
return on;
}
};

int main() {
Animatee matee;
matee.addEvent(new Add());

//cout << "Before: " << matee.value << " After: " << matee.act().value << endl; <~~~ Undefined btw, acting on the object twice in one "statement"double before = matee.value;
cout << "Before: " << before << " After: " << matee.act().value << endl;

matee.addEvent(new Subtract());
before = matee.value;
cout << "Before: " << before << " After: " << matee.act().value << endl;

matee.addEvent(new Subtract());
before = matee.value;
cout << "Before: " << before << " After: " << matee.act().value << endl;

matee.addEvent(new Add());
matee.addEvent(new Add());
matee.addEvent(new Add());
before = matee.value;
cout << "Before: " << before << " After: " << matee.act().value << endl;

matee.addEvent(new Multiply());
before = matee.value;
cout << "Before: " << before << " After: " << matee.act().value << endl;

before = matee.value;
cout << "Before: " << before << " After: " << matee.act().value << endl;

return 0;
}
2

Другие решения

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

Есть две разные проблемы. Первое — это возможное изменение параметров внутренней анимации (что может быть непрозрачным для механизма позиционирования), а второе — изменение скорости (которое не является непрозрачным).

Я бы решил оба ортогонально.

Сосредоточив внимание на скорости, следующий вопрос — как вы хотите, чтобы декораторы сочиняли друг с другом. Добавляют ли они, умножают, заменяют, формируют верхние или нижние границы выходной скорости?

К какой информации о местном штате им разрешен доступ?

Предполагая, что им задают положение вдоль кривой, и только последний декоратор скорости означает что-либо, std::function<double(double)> подойдет как тип декоратора скорости.

Это на том же уровне эффективности, что и вызов virtual функция или два. И инжектор или декоратор может захватывать все, что хочет для внутреннего состояния …

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector