Я не знаю, как назвать эту проблему, поэтому я постараюсь объяснить как можно лучше.
Я хочу иметь возможность переключать стратегии в зависимости от типов двух разных объектов. Чтобы сделать это, я думаю пометить объекты с типом enum и иметь «реестр» (массив) этих стратегий. В идеале, к правильной стратегии можно обратиться с помощью некоторой простой операции, например, побитового оператора между двумя типами.
Этот псевдокод может облегчить понимание того, что я пытаюсь объяснить:
enum Type { A, B, C }
struct Object {
Type type;
}
class ActionRunner {
vector<Strategy> strategies;
void registerStrategy(type1, type2, strategy) {
strategies[type1 operator type2] = strategy;
}
void runStrategyFor(type1, type2) {
strategies[type1 operator type2].execute();
}
}
Это было бы легко решить с помощью карты, но я бы хотел использовать массив или вектор, потому что карта кажется излишним для такой проблемы, и использование массива, вероятно, намного быстрее.
Так что проблема в том, что я не знаю, каким оператором я мог бы воспользоваться, чтобы выбрать «позицию» правильной стратегии. Я думал о нескольких комбинациях, но кажется, что все они в какой-то момент вызывают столкновения с различными комбинациями.
У кого-нибудь есть какие-нибудь подсказки / советы о том, что я могу использовать для этого?
PS: я знаю, что преждевременная оптимизация — это плохо, но я просто пытаюсь выяснить, можно ли решить эту проблему простым способом.
——- РЕДАКТИРОВАТЬ ————————————————
В свете ответов я немного подумала над проблемой и пришла к выводу, что то, что я имела в виду под этим вопросом, не так, как мне бы хотелось. Я попытаюсь переформулировать проблему, которую пытаюсь решить, используя этот вопрос.
Я хотел бы иметь структуру класса, в которой есть объекты определенного типа «BaseClass» и объект «процессор», который принимает два объекта, производных от «BaseClass», и выполняет правильную стратегию для них. Что-то вроде этого:
class Processor {
void run (DerivedA a, DerivedB b);
}
class BaseClass {}
class DerivedA: public BaseClass {}
class DerivedB: public BaseClass {}
BaseClass a = new DerivedA;
BaseClass b = new DerivedB;
processor.run(a, b)
В соответствии с тем, что я понимаю, это не сработает, как я ожидаю, если то, что передается в качестве параметров для запуска, является ссылками, что я и предпочел бы сделать. Есть ли способ сделать это без слишком сложного кода? (тройная отправка !?)
Я имею в виду что-то вроде двойной отправки в сочетании с подчиненным (процессором) объектом, который, я думаю, будет работать, но это кажется ужасно сложным и, вероятно, болью в обслуживании и расширении.
Спасибо!
Во втором предложении вашего вопроса мне позвонили:
Я хочу иметь возможность переключать стратегии в зависимости от типов двух разных объектов.
Похоже, вы хотите выполнить двойная отправка. Смотрите вопрос (в частности, ответы на вопрос ;-)) на Двойная рассылка / мультиметоды в C ++ о том, как реализовать это в C ++.
Это классический пример использования map
вместо массива. Массив на самом деле является частным случаем map
с ключом, определенным как целое число. В вашем случае ключ является кортежем, поэтому простой массив не подойдет, и вы столкнетесь с коллизиями (даже если вам повезет с вашим конкретным вводом, ваш код будет крайне ненадежным).
Вы можете иметь промежуточное решение, между простым array
а также map
: 2D array
с вашими 2 типами, служащими индексами для строк и столбцов.