c# - simple - ¿Este es el patrón de creación del Método de Fábrica?
patrones de diseño c# (20)
¡Recupere el poder ahora mismo! Simplemente suelte ''Tipo'' de la fraseología. ScheduleFactory FTW. Espera, ¿es esta una fábrica para ''Horarios'' o ''Horario''? Si se trata de un cronograma, la fábrica debe llamarse ''ScheduleItemFactory''. Se expresivo !!!
He estado utilizando el patrón de creación de métodos de fábrica por un tiempo. Me acaban de decir que esto:
public static class ScheduleTypeFactory
{
public static IScheduleItem GetScheduleItem(ScheduleTypeEnum scheduleType)
{
IScheduleItem scheduleItem = null;
switch (scheduleType)
{
case ScheduleTypeEnum.CableOnDemandScheduleTypeID:
{
scheduleItem = new VODScheduleItem();
break;
}
case ScheduleTypeEnum.BroadbandScheduleTypeID:
{
scheduleItem = new VODScheduleItem();
break;
}
case ScheduleTypeEnum.LinearCableScheduleTypeID:
{
scheduleItem = new LinearScheduleItem();
break;
}
case ScheduleTypeEnum.MobileLinearScheduleTypeID:
{
scheduleItem = new LinearScheduleItem();
break;
}
}
return scheduleItem;
}
}
no es un patrón de creación de método de fábrica por mi líder "Tech" sin decirme por qué o darme su interpretación. Le pedí amablemente una explicación y ella me dijo que no tenía tiempo. Me dijeron que simplemente cambie el nombre. Si estoy equivocado, sin duda aceptaré que lo he implementado de forma incorrecta durante años. ¿Es así como USTED implementaría el patrón de creación de métodos de fábrica? Gracias por adelantado.
A mí me parece una fábrica (básica) ... en muchas fábricas la implementación es más compleja (tal vez con tipos resueltos en tiempo de ejecución), pero eso no es (AFAIK) un requisito. La única otra crítica que habría agregado es combinar los casos, y hacer algo más dramático si no reconoces el tipo ...
Bueno, Wikipedia dice que es un método de fábrica:
public class ImageReaderFactory
{
public static ImageReader getImageReader( InputStream is )
{
int imageType = figureOutImageType( is );
switch( imageType )
{
case ImageReaderFactory.GIF:
return new GifReader( is );
case ImageReaderFactory.JPEG:
return new JpegReader( is );
// etc.
}
}
}
Claro que parece el patrón de fábrica para mí. No veo nada malo con su implementación.
Del patrón de método de fábrica :
La esencia del Patrón de Fábrica es "Definir una interfaz para crear un objeto, pero deje que las subclases decidan a qué clase instanciar. El método de Fábrica permite a una clase diferir la instanciación a subclases".
Esto es exactamente lo que estás haciendo.
Como nota al margen: una buena regla empírica es que cada vez que alguien le dice algo y no puede o no quiere proporcionar un fundamento para su declaración, existe una buena posibilidad de que no esté calificado para hacer la declaración.
Creo que tradicionalmente se lo llama el patrón simple de fábrica para distinguirlo del patrón ''real'' de Abstract Factory . Puede ser que no estés siguiendo un tipo de práctica de denominación interna. Sin embargo, ella realmente debería explicarse.
De hecho, es una "fábrica" en la que tiene un método que devuelve una instancia específica del IScheduleItem
basado en algún tipo de lógica; sin embargo, probablemente no sea la mejor implementación o la más fácil de mantener, dado que está utilizando una instrucción switch.
El fragmento de código es lo que en Head First Design Patterns se llama "The Simple Factory" (página 117).
La principal diferencia con el patrón de método de fábrica es ConcreteCreator (compare el diagrama en la esquina superior derecha), que es una clase simple en su caso.
En el "patrón real", la clase de fábrica es abstracta con una clase de fábrica abstracta. Entonces, hay un nivel de abstracción más. Sin embargo, para muchos casos de uso, su fábrica simple es suficiente.
Simple Factory Simple Factory http://yuml.me/7221a4c9 Factory Method Pattern Factory Method Pattern http://yuml.me/3d22eb4e
Es el patrón de método de fábrica, al menos según Wikipedia: http://en.wikipedia.org/wiki/Factory_method_pattern
Ese es el patrón de fábrica, pero no es necesariamente la variante más sostenible. Una variante más IScheduleItem
mantener mantendría algún tipo de mapa global entre los valores de ScheduleTypeEnum
y los subtipos concretos actuales de IScheduleItem
; de ese modo, podría reemplazar la instrucción switch
con una búsqueda del mapa.
¿Por qué es más fácil de mantener? Debido a que los autores de las subclases pueden agregar pares al mapa en el sitio donde derivan la clase , en lugar de la función de fábrica GetScheduleItem()
. Por lo tanto, este último nunca necesita actualización; está constantemente actualizado.
En C ++ puedes hacer esto usando un std::map
global - para cada subclase concreta, el autor de la subclase agrega una variable global ficticia que en realidad solo registra la clase (al agregar al mapa) en su constructor, que se ejecuta en tiempo de inicio del programa. Estoy seguro de que hay una manera conveniente de hacer lo mismo en C #.
(El gurú de C ++ Herb Sutter tiene una descripción entretenida aquí , pero es bastante C ++ - pesado).
Eso es un patrón de fábrica de libros de texto.
Algunos textos lo llaman Simple Factory Patteren, pero nunca he visto ningún criterio para lo que significa "Simple".
En mi práctica, un patrón de fábrica es cualquier creación inteligente de una clase concreta que corresponda a una interfaz deseada.
Pero ¿por qué luchar contra su liderazgo tecnológico por nombrar un método? Renombrarlo, seguir con tu vida.
Estoy de acuerdo en llamar al método un "Método de Fábrica", aunque el diseño no es estrictamente un "Patrón de Método de Fábrica".
Aquí hay un punto clave (de Wikipedia):
... El método Factory permite que una clase difiera la instanciación a subclases ".
Como su clase es estática y estática (por lo tanto, no es virtual), no es posible "posponer".
Conceptualmente, tenga en cuenta también que esta implementación, aunque proporciona encapsulación, no desacopla ni retrasa ninguna decisión.
Habiendo dicho eso, el mismo artículo de Wikipedia presenta este esquema como una variante del "Patrón de método de fábrica".
Resumen del resumen: En mi opinión, este fragmento no es una implementación adecuada del "Patrón de diseño del método de fábrica OO", ya que no satisface "una instancia de aplazamiento de clase a subclases". Sin embargo, personalmente me referiría libremente a esta solución como "método de fábrica".
Para que sea un patrón de método de fábrica real , debe permitir que las subclases anulen el método. Es decir, la clase de fábrica (ScheduleTypeFactory) debe ser extensible (es decir, no estática) y GetScheduleItem debe ser virtual.
La explicación más simple del patrón de fábrica, que aprendí de una clase de patrones y práctica, fue que si confías en otra clase para crear las instancias de tu clase, entonces estás usando el patrón de fábrica.
Por supuesto, muchas veces desea agregar una capa de indirección haciendo que su clase sea abstracta o una interfaz.
Esta es una vista muy simplificada, pero de cualquier forma, estás usando el patrón de fábrica.
Lo que el líder tecnológico probablemente piense es que el patrón Factory es reemplazar un constructor en el mismo objeto, no devolver subclases, o tal vez solo devolver subclases de una superclase, no de un objeto no relacionado. Está mal, pero ese es probablemente el pensamiento.
El hecho de que Wikipedia liste su patrón como ejemplo muestra que es correctamente un patrón de fábrica. Los patrones se definieron para proporcionar un lenguaje común para soluciones comunes, por lo que claramente si Wikipedia muestra esto como un ejemplo, es parte del lenguaje común. Un debate académico sobre lo que el "Patrón de Fábrica" es en cierto sentido abstracto pierde el sentido de los patrones.
Me sorprende que muchos digan que este es el patrón de fábrica. (Así que es probable que esté pensando en esto, así que háganmelo saber).
Me parece que lo que tienes allí es solo una parte del diseño. Si lo llama desde su cliente, se lo conoce como una fábrica "simple", pero en realidad no se considera un patrón de diseño. (No me malinterpreten, lo hago todo el tiempo).
El patrón de diseño de fábrica indicará que su fábrica hereda / implementa una interfaz abstracta de fábrica / fábrica.
Luego, en su clase que necesita usar la fábrica (el cliente), establece el tipo de fábrica en el resumen / interfaz, creando una fábrica de concreto: es decir, -> Fábrica de fábrica = nueva ConcreteFactory ();
La fábrica de concreto crearía entonces su IScheduleItem (dejándolo en fábrica para crear realmente el tipo concreto).
Al final, creo que todo se trata de un acoplamiento flexible. Mientras que una fábrica "simple" combina holgadamente la construcción del producto del cliente, no desacopla la fábrica. El patrón de fábrica también desacopla la fábrica.
Por otra parte, es temprano, no he tomado café, y tengo la desagradable costumbre de publicar respuestas absolutamente horribles que omiten todo el sentido de la pregunta.
Parece un patrón básico de fábrica para mí. Tengo curiosidad por saber por qué su líder tecnológico no cree que esto sea un patrón.
También estoy decepcionado de que ella no se tome el tiempo para explicar las cosas. Habiendo sido un líder tecnológico antes en un equipo, es curioso tomarse el tiempo para explicar sus decisiones.
Parece un patrón de fábrica para mí. Dile a tu líder tecnológico que no tienes tiempo para explicar por qué está equivocada.
Sí, ese es el patrón de fábrica bien. Tu ventaja técnica es incorrecta.
Sí, este es un patrón de fábrica. Mi único comentario sería que fallas silenciosamente en los valores enum que no manejas específicamente. Eso se puede esperar, pero me gusta agregar lo siguiente al final de las declaraciones como esa
default:
throw new InvalidOperationException("Invalid Enum Value");
Tu tecnología está en lo cierto al renombrar el método:
public static IScheduleItem GetScheduleItem(ScheduleTypeEnum scheduleType)
La acción del método no es obtener algo, es crear algo. ¿Cómo se decide qué scheduleType se debe crear? Parece que la lógica debe ser encapsulada, no el interruptor del tipo.
¿Por qué también la estática en la clase? ¿De dónde lo estás usando?
public class ScheduleTypeFactory
{
public static IScheduleItem createScheduleFrom(ScheduleTypeEnum scheduleType)
{
switch (scheduleType)
{
case ScheduleTypeEnum.CableOnDemandScheduleTypeID:
case ScheduleTypeEnum.BroadbandScheduleTypeID:
return new VODScheduleItem();
case ScheduleTypeEnum.LinearCableScheduleTypeID:
case ScheduleTypeEnum.MobileLinearScheduleTypeID:
return new LinearScheduleItem();
}
raise InvalidSchedule;
}
}
Su ventaja es correcta (lo siento por el formateo, pero esta respuesta necesita algo de eso para poder verla entre la línea principal que dice que el líder es un idiota): ni el libro de GOF ni Head First son un método de fábrica.
GoF:
"Defina una interfaz para crear un objeto, pero deje que las subclases decidan qué clase instanciar. El Método de Fábrica permite que una clase difiera la instanciación a subclases ".
En su ejemplo, no es una subclase la que decide .
¿Lo has implementado incorrectamente todos estos años? No, simplemente no ha implementado el patrón de fábrica, pero lo que a veces se conoce como el ''Patrón de Fábrica Simple'', que probablemente ha hecho bien el trabajo.