Estoy refaccionando una sola clase de línea 3000 + con una red enmarañada de condicionales e interruptores en un conjunto de clases de trabajadores. Anteriormente parte de la constructora sería seleccionar qué "tipo" de que hay que utilizar a través de un código como el siguiente:¿Cómo seleccionar aleatoriamente una clase para instanciar sin usar el interruptor?
enum Type { FOO, BAR, BAZ };
Type choices[] = { FOO, FOO, BAR, BAZ }; // weighted towards FOO
m_type = choices[rand()%4];
[...later...]
void Run() {
switch (m_type) {
case FOO: do_foo(); break;
case BAR: do_bar(); break;
case BAZ: do_baz(); break;
}
}
Después de refactorización tengo separados TypeFoo
, TypeBar
y TypeBaz
clases que cada uno tiene sus propias Run()
métodos para hacer su trabajo . Lamentablemente, es complicado el código de selección de clase. No sé de ninguna manera de mantener una lista de posibles clases de construir, así que tengo esto:
Type *m_type;
switch (mrand()%4) {
case 0: case 1: m_type = new TypeFoo(); break;
case 1: m_type = new TypeBar(); break;
case 2: m_type = new TypeBaz(); break;
}
Esto es todavía vale la pena el cambio porque el código de inicialización no se llama con regularidad, pero su momento más difícil de modifique esta lista, cambie las ponderaciones, etc.
¿Es relativamente sencillo lograr la claridad del código original?
+1: Interesante pregunta ... :-) hacer todas esas clases heredan de una sola clase base? –
Esto sería un poco mejor: 'interruptor (mrand()% 4) { caso BAR: t = new TypeBar(); descanso; case BAZ: t = new TypeBaz(); descanso; predeterminado: t = new TypeFoo(); descanso; // ponderado hacia Foo } ' – Yourpalal
¿Por qué está etiquetado como' plantilla', cuando la selección tiene que suceder en el tiempo de ejecución? – iammilind