Answer the question
In order to leave comments, you need to log in
Matrix polymorphism?
Colleagues, good afternoon.
An architectural problem arose, which I did not master right away.
So, the application has some kind of data processing that depends on two parameters (m, n). Depending on the combination of parameters, some actions can be performed, sometimes the same, for different parameters, sometimes different. In total, we have a matrix MxN, where in each cell of which there is a certain action A. The ratio of the number of options for parameters and actions is approximately the following M~=N~=A/3 .
The old implementation is made in the form of a giant switch by M with nested switches by N (only 230 lines in Delphi).
A typical piece looks something like this (in pseudocode)
case m_5:
{
switch(n)
case (n3,n5,n6,n18): {какой-то небольшой код}
case (n4,n6,n8,n9): {какой-то небольшой код}
default: {какой-то небольшой код}
}
Answer the question
In order to leave comments, you need to log in
It seems that in McConnell's book "Perfect Code" there was a chapter about tabular methods. Read it (pages 20-30 in total), maybe it will help you. The simplest option that I came up with right away:
create a table, in each cell of which there will be a callback to the desired function.
Perhaps I'm wrong, and you definitely need classes.
We implement all Ai functions:
function() A1() {};
function() A2() {};
function() A3() {};
...
Next, we take pointers to all these functions and write them to Pi;
Next, we take the MxN matrix and write the index of the desired function into the corresponding i, j.
Then, for i, j, we take a pointer to the desired function and execute it.
Something like this.
It can be implemented without pointers by making one function A(i) that performs the desired function for the required i.
PS Perhaps, I firmly believe that the functions are similar, and differ only in parameters, which can improve the implementation.
If M is a set of classes and N is a set of classes, then this is a classical visitor pattern.
I would probably do something like this:
typedef void (*HandlerFunction)(<params>); // or typedef std::function<void (params)> HandlerFunction;
struct HandlerKey { int m; int n; } // реализуем так же операторы для сравнения, конструктор ...
typedef std::map<HandlerKey, HandlerFunction> HandlerMap;
void init(HandlerMap & m)
{
m[HandlerKey(m1, n2)] = HandlerFunction1;
m[HandlerKey(m1, n2)] = HandlerFunction2;
m[HandlerKey(m2, n1)] = HandlerFunction1;
m[HandlerKey(m2, n2)] = HandlerFunction3;
...
}
void process(const HandlerKey & key, <params>)
{
HandlerMap::iterator it = handlerMap.find(key);
if (it == handlerMap.end())
std::runtime_error("No handler for key " + key.toString());
it->second(<params>);
}
The assignment can be done as a function with a variable number of arguments, I think:
init(ValueType value, int line, int column, ...); // prototype
init(value, line, column1, column2, column3); // this is what the call will look like
then there will be no m*n assignments.
If you use a fresh version of gcc, then the same can be done through variadic templates (I really don’t know why :) )
You have described one of the best solutions: M classes of N methods. Duplication is easy to avoid by implementing everything once, and in other methods just call the already implemented ones. Your goal for OOP style is googling for the phrase "multiple polymorphism". It seems that Meers offered a solution in the form of map<key, function>, which simply writes pointers to functions, as you were already offered above.
Дублирования легко избежать, реализовав всё по 1 разу, а в остальных методах просто вызывать уже реализованные
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question