Допустим, у меня есть кусок кода:
A1 a;
A2 b;
a= function1_A();
b= function2_A();
И тогда я хочу сделать это по-другому:
B1 a;
B2 b;
a= function1_B();
b= function2_B();
И я делаю Шаблон дизайна стратегии, чтобы иметь и то, и другое, и выбрать то, что мне нужно. Но дело в том, что код такой же, за исключением того, что все А теперь являются B. Конечно, то, что это делает, может быть совершенно другим, но это выходит за рамки.
Есть ли способ разработать код, чтобы предотвратить такое повторение?
Если бы это были просто функции, я знаю, я мог бы сделать это с абстрактным суперклассом и получить его.
a=function1_SUPER();
и тогда у каждого есть правильная реализация как:
function1_SUPER(){ function1_A();}
но это все еще генерирует много кода. Плюс не работает с именами классов, как, например, смена A1 на B1, верно?
Я бы сформулировал задачу в двух частях, которые я вижу: во-первых, выделяя по типу (А1, А2 и В1, В2) и во-вторых, различая по инициализации переменных. Поскольку вы говорите, код все тот же, но типы не шаблоны приходят на ум. Итак, моя первая попытка будет:
template <class X1, class X2>
struct MyStrategy {
void foo()
{
X1 a = /* create appropiate X1 */;
X2 b = /* create appropiate X2 */;
// code that is the same for both except for the types...
}
};
Конечно, функция будет иметь параметры и / или тип возвращаемого значения, но вы получите суть.
Теперь ко второй части, которую я оставил в комментариях: инициализация значений. Я достиг бы этого с помощью какого-то политического дизайна. Первый набросок:
template <class X1, class X2>
struct X1X2Creator;
template <>
struct X1X2Creator<A1, A2> {
A1 createX1() { return function1_A(); }
A2 createX2() { return function2_A(); }
};
template <>
struct X1X2Creator<B1, B2> {
B1 createX1() { return function1_B(); }
B2 createX2() { return function2_B(); }
};template <class X1, class X2>
struct MyStrategy : X1X2Creator<X1, X2> {
void foo()
{
X1 a = this->createX1();
X2 b = this->createX2();
// code that is the same for both except for the types...
}
};
Обратите внимание, что вы должны вызвать create-функции через this->createX1()
, из-за их зависимых имен, в противном случае компилятор должен пожаловаться. Вы также можете явно определить функции (X1X2Creator<X1, X2>::createX1()
).
Вы можете улучшить этот дизайн в соответствии со своими потребностями, например, не используя наследование, а создавая экземпляр X1X2Creator и вызывая функции или делая их статическими. Если вы хотите использовать больше комбинаций разных типов, используйте одну политику создания для каждого типа:
template <class X1, class X2>
struct MyStrategy {
void foo()
{
X1 a = CreationPolicy<X1>::create();
X2 b = CreationPolicy<X2>::create();
// code that is the same for both except for the types...
}
};
Если вы хотите использовать разные политики для одних и тех же типов, укажите классы политик в качестве параметров шаблона:
template <class X1, class X2,
class X1Creator = CreationPolicy<X1>,
class X2Creator = CreationPolicy<X2>>
struct MyStrategy {
void foo()
{
X1 a = X1Creator::create();
X2 b = X2Creator::create();
// code that is the same for both except for the types...
}
};
НТН
Я думаю, что вы должны использовать шаблон. Например:
#include <iostream>
template <class C1, class C2> class MyClass
{
public:
C1 *function1()
{
return new C1();
};
C2 *function2()
{
return new C2();
};
};
int main()
{
MyClass<int, double> intDoubleClass;
int *a1 = intDoubleClass.function1();
double *a2 = intDoubleClass.function2();
return 0;
}