Una implementación de plantilla podría quedar así:
class Factory {
public:
enum which {
foo, bar, baz
};
template<which w>
A* newA(...);
...
};
template<Factory::which w>
A* Factory::newA(...) {
/* default implementation */
throw invalid_argument();
}
template<>
A* Factory::newA<Factory::foo>(...) {
/* specialization for a 'foo' style A */
...
}
....
Esto requiere que el valor utilizado para determinar qué newA
se llama ser conocido en tiempo de compilación. Podría utilizar un const char *
como parámetro de plantilla, pero no se garantiza que funcione en todos los compiladores.
Otra opción más es crear fábricas auxiliares, una para cada método de creación de fábrica, y almacenarlas en el mapa. Esta no es una gran ventaja sobre el almacenamiento de punteros de método, pero sí le permite definir un método de creación predeterminado y simplifica la obtención de elementos del mapa (no es necesario verificar que la clave exista, porque obtendrá una fábrica predeterminada). En el lado negativo, se agregará una entrada para cada clave desconocida al mapa.
Además, si utiliza un enum
en lugar de una cadena para el tipo de clave, no debería tener que preocuparse por comprobar si existe una clave en el mapa. Si bien es posible que alguien pase una clave enum
no válida a newA
, tendrían que lanzar explícitamente el argumento, lo que significa que no lo van a hacer por accidente. Me está costando imaginar un caso en el que alguien causaría un bloqueo intencionalmente en newA
; los escenarios potenciales implican seguridad, pero un programador de aplicaciones podría bloquear la aplicación sin usar su clase.
¿Cuál es el objetivo general? En la mayoría de los casos en que las personas usan interruptores, el polimorfismo es lo que deberían usar. – outis
+1 reemplazar interruptores con búsquedas de tabla es algo que me gusta hacer en lenguajes dinámicos. –
Tengo una clase de fábrica, que tendrá varios métodos de constructor devolviendo clases de tipo A. La idea es hacer algo como A * aClass = Factory-> newA ("key"); . Luego, la fábrica usaría la "clave" para invocar el método correcto para construir una clase A y devolverla en consecuencia. – Goles