2010-12-11 7 views
27

Todos sabemos la diferencia entre un Constructor y un método definido por el usuario Initialize() fundamentalmente.Método Initialize() vs Constructor(), uso adecuado en la creación de objetos

Mi pregunta se centra en las mejores prácticas de diseño para la creación de objetos. Podemos poner todos los códigos Initialize() en Constructor() y viceversa (mover todo el código de calentamiento al método Initialize y llamar a este método desde Constructor).

Actualmente, diseñando una nueva clase, creo cualquier instancia nueva dentro de constructor() y muevo cualquier otro código de calentamiento al método Initialize().

¿Cuál es el mejor punto de equilibrio en su opinión?

Respuesta

23

creo que hay varios aspectos que deben ser tomados en consideración:

  • Un constructor debe inicializar un objeto de una manera que está en un estado utilizable.

  • Un constructor solo debe inicializar un objeto, no realizar un trabajo pesado.

  • Un constructor no debe llamar directa o indirectamente a miembros virtuales o a un código externo.

Por lo tanto, en la mayoría de los casos, no se debe requerir un método de inicialización.

En los casos en que la inicialización implica algo más que poner el objeto en un estado utilizable (por ejemplo, cuando se necesita realizar un trabajo pesado o se necesita llamar a miembros virtuales o externos), es una buena idea utilizar un método de inicialización.

+0

Bien puesto. En el pasado, también me he inclinado hacia el uso de los métodos 'initialize()' sobre los constructores cuando no se instanciaba directamente el objeto, como usar un patrón de fábrica. ¿Crees que esta es una consideración relevante? – Ray

3

Me he encontrado pensando en esto hace bastante poco tiempo (de ahí la búsqueda de esta pregunta) y aunque no tengo una respuesta pensé en compartir mis pensamientos.

  • constructores idealmente 'sólo debe establecer el estado del objeto, es decir: unos pocos:

this.member = member;

En mi opinión, esto juega muy bien con la COI, la herencia, la prueba y solo huele bien.

elevación pesada Sin embargo a veces es necesario así que lo que he estado tratando de hacer es:

  • pase en el trabajo pesado.

Eso significa abstraer ese código de inicialización a otra clase y pasarlo. Esto suele ser posible si el trabajo pesado no es realmente responsabilidad de los objetos, por lo que esto realmente refactores a un código más agradable.

Si esto no es posible y necesita inicializar el estado de su clase antes del uso, agregue un método de inicialización.Esto le añade la dependencia temporal en el código, pero esto no es necesariamente algo malo, especialmente cuando se utilizan contenedores IoC:

Say CarEngine requiere un DrivingAssistComputer, y los DrivingAssistComputer tiene que hacer la inicialización pesada, es decir, cargar todos los parámetros, los controles de la condición atmosférica, etc. Otra cosa a tener en cuenta es que CarEngine no interactúa directamente con el DrivingAssistComputer, solo necesita que esté presente, haciendo lo suyo en el costado. De hecho, es posible que el motor no funcione correctamente sin DrivingAssistComputer haciendo lo suyo en el fondo (cambiando algún estado en algún lugar). Si estamos utilizando IoC entonces tenemos:

// Without initialise (i.e. initialisation done in computer constructor) 
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) { 
    this.injectors = injectors; 
    // No need to reference computer as we dont really interact with it. 
} 

... 

Así que lo que tenemos aquí es un argumento del constructor marca computer como una dependencia, pero en realidad no lo utilice. Así que esto es feo, pero vamos a añadir un método de iniciación:

public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) { 
    this.injectors = injectors; 
    // This ofcourse could also be moved to CarEngine.Initialse 
    computer.Initialise(); 
} 

... 

Aún no es una clase de cohesión, pero al menos sabemos que dependemos de ordenador, incluso cuando no estamos interactuando directamente con él fuera del constructor.

Otra opción por supuesto es tener un CarEngineFactory que hace:

CarEngine CreateEngine(FuelInjectors injectors) { 
    new DrivingAssistComputer().Initialise(); 
    return new CarEngine(injectors); 
} 

... 

Sin embargo, me parece fábricas y la COI acaba de confundir la matriz por lo que me gustaría ir por la segunda opción.

Me encantaría escuchar algunas ideas sobre esto.

Editar 1: Otra opción que omití anteriormente es tener el método Initialise pero mover esta invocación al módulo de inicialización de IoC. Entonces, la creación y la inicialización todavía están un tanto encapsuladas.

+0

+1 para 'pasar en el trabajo pesado' - esto tiene sentido para mí –

Cuestiones relacionadas