2009-03-30 24 views
21

he buscado una buena ejemplo de un patrón Constructor (en C#), pero no puede encontrar uno, ya sea porque no entiendo el patrón Builder o que estoy tratando de hacer algo que fuera nunca intencionado Por ejemplo, si tengo un automóvil abstracto y métodos abstractos para crear partes de automóviles, debería poder enviar mis 30 opciones al Director, hacer que construya las piezas que necesito y luego construir mi automóvil. Sin importar qué auto, camión, semi, etc. produzca, debería ser capaz de "conducirlo" exactamente de la misma manera.Diseño Patrón: Constructor

El primer problema es la mayoría de los ejemplos de valores de propiedades de código duro en las partes concretas, que realmente creo que deberían provenir de una base de datos. Pensé que la idea era enviar mis elecciones al Director (desde una fuente de datos) y hacer que el constructor creara un producto personalizado basado en mis datos.

El segundo problema es que quiero que los métodos del constructor realmente creen las piezas y luego las asignen al producto, no cadenas de paso sino partes del producto real fuertemente tipadas.

Por ejemplo, quiero crear un formulario sobre la marcha teniendo un Builder fabricando campos de formulario para mí, incluyendo una etiqueta, una sección de entrada, validación, etc. De esta forma puedo leer el objeto de mi ORM, verificar fuera de los metadatos del objeto, páselo a mi Creador y agregue el resultado de control de usuario recién creado a mi formulario web.

Sin embargo, todos los ejemplos de Builder que encuentro solo tienen datos codificados en lugar de pasar opciones del código principal al generador y expulsar un producto personalizado. Todo parece ser una gran declaración de caso estática. Por ejemplo, si tengo tres parámetros con 10 opciones cada uno, no quiero construir 30 métodos concretos de Builder, solo quiero crear lo suficiente para fabricar las propiedades que requiere mi producto, que pueden ser solo tres.

Estoy tentado de que el Director exista solo en el código principal. Debería haber una manera de determinar automáticamente qué método de compilación concreta llamar similar al polimorfismo y las sobrecargas de métodos (aunque ese es un muy mal ejemplo) en lugar de usar una declaración de caso dentro del patrón. (Cada vez que necesito agregar un nuevo tipo de producto, tendré que modificar el Director existente, lo cual es malo).

+0

tal vez, lo que falta en el patrón del generador, es que los objetos no se destruyen al final, por lo que sugiero que agregue esto más adelante si no ha entendido el patrón ... – Tobias

+0

No es realmente lo que quiere, pero revise estos artículos:
[la descripción del patrón] (http://sourcemaking.com/design_patterns/builder)
[muestra de implementación C#] (http://sourcemaking.com/design_patterns/builder/c%2523)
Espero que esto ayuda – 0x49D1

Respuesta

10

Iré al ejemplo de C# en el artículo de Wikipedia here.

El primer problema es que la mayoría de los ejemplos tienen valores de propiedad de código duro en las partes concretas, lo que realmente creo que debería provenir de una base de datos. Pensé que la idea era enviar mis elecciones al Director (desde una fuente de datos) y hacer que el constructor creara un producto personalizado basado en mis datos.

En este caso, tendría la clase implementando PizzaBuilder que sabe cómo recuperar datos de una base de datos. Puedes hacerlo de varias maneras.

Uno sería hacer un HawaiianPizzaBuilder. Cuando la clase lo inicializa, consulta la base de datos de una pizza hawaiana y recupera la fila. Luego, cuando se invocan los diversos métodos Build (x), se establecerían las propiedades en el campo correspondiente de la fila de la base de datos recuperada.

Otro sería simplemente hacer un PizzaDatabaseBuilder y asegurarse de que al inicializar la clase le pase el ID de la fila que necesita para ese tipo de pizza. Por ejemplo en lugar de

waiter.PizzaBuilder = new HawaiianPizzaBuilder(); 

Se utiliza

waiter.PizzaBuilder = new PizzaDatabaseBuilder("Hawaiian"); 

segundo problema es que quieren que los métodos constructor para crear realmente las partes y luego asignarlos al producto, no pasar cadenas pero real inflexible de tipos de productos partes.

No debería ser un problema. Lo que necesita es otro patrón de tipo Fábrica/Constructor para inicializar los campos de la Pizza. Por ejemplo

en lugar de

public override void BuildDough() { pizza.Dough = "pan baked"; } 

que haría algo como

public override void BuildDough() { pizza.Dough = new DoughBuilder("pan baked"); } 

o

public override void BuildDough() { pizza.Dough = new PanBakedDoughBuilder(); } 

DoughBuilder puede ir a otra mesa en su base de datos para rellenar correctamente un PizzaDough Clase.

+0

Buena respuesta. Si usamos clases de fábrica declaradas estáticamente, no necesitaríamos el nuevo operador. La llamada del constructor de Tobiask también es sorprendente, como jQuery. La respuesta es donde no necesitarías un director es lo que estoy tomando de todo esto. El truco será codificarlo de verdad. Muchas gracias. –

+0

Cuanto más entienda esta respuesta, más se dará cuenta de cuánto sabe RS Conley. :) +100 si pudiera. –

0

Yo diría que no puede evitar ninguno de estos: tener pocas sobrecargas para sus piezas y tener una declaración de caso/si en algún lugar de la pila. También tener que modificar su código al agregar una nueva clase podría ser su única opción.

Dicho esto, puede obtener ayuda con algunos otros patrones, a saber, la fábrica que podría ayudarle en el proceso de construcción. También el uso sensato del polimorfismo (por ejemplo, todas las partes heredan de algún tipo, ya sea clase o interfaz) puede reducir la cantidad de ifs/casos y sobrecargas.

Espero que esto ayude.

19

Parcialmente la llamada de un Builder tiene el siguiente aspecto:

Car car = new CarBuilder().withDoors(4).withColor("red").withABS(true).build(); 
+2

Ese no es realmente el patrón del generador como se describe en Patrones de diseño. El patrón está diseñado para crear diferentes representaciones de la misma fuente. Por ejemplo, un compilador que usa un analizador pero tiene diferentes backends para x86, x64 y Java Byte Code. –

+4

Puede que no sea exactamente como lo describen los Patrones de diseño, pero asegura que el objeto creado tenga todas las propiedades establecidas correctamente. También puede hacer que el constructor de objetos use una interfaz fluida ... pero eso es para otra pregunta – Kane

10

nunca he pensado en ello de esta manera, pero LINQ (el patrón, no la sintaxis) es en realidad un constructor, ¿verdad?

Es una interfaz fluida que crea una consulta y puede crear consultas en diferentes representaciones (SQL, consultas de objetos en memoria, consultas de servicios web, Bart de Smet incluso escribió una implementación de Linq-to-Excel).

+0

Sí, absolutamente. –