method - patrones de diseño c#
¿Cuándo usar el patrón de método de fábrica? (11)
Aunque esto no es necesariamente su uso principal, es bueno para algo donde hay instancias especializadas de una clase:
public ITax BuildNewSalesTax()
public ITax BuildNewValueAddedTax()
Necesita ambos métodos para construir un objeto fiscal, pero no quiere tener que depender de usar "nuevo" cada vez porque los constructores pueden ser complejos. De esta manera encapsulo todos los cambios en un solo método que es claro para otros para el mantenimiento futuro.
¿Cuándo usar el patrón de método de fábrica?
Por favor, ¿me da alguna idea específica sobre cuándo usarlo en el proyecto? y ¿cómo es una mejor manera que una nueva palabra clave?
Creo que es cuando quieres que tu aplicación se acople y amplíe en el futuro sin cambios de codificación.
He escrito una publicación en el blog sobre por qué escogí el patrón de fábrica en mi proyecto y es posible que le brinde más información. El ejemplo está en PHP, pero creo que es aplicable en general a todos los idiomas.
http://www.mixedwaves.com/2009/02/implementing-factory-design-pattern/
El patrón de fábrica trata con la creación de instancias de objetos sin exponer la lógica de creación de instancias. En otras palabras, una fábrica es en realidad un creador de objetos que tiene una interfaz común.
Permite que la subclase decida qué clase se instanciará.
Considere el siguiente ejemplo:
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
//Store is ordering the factory to get office shoes
Shoe shoe = ShoeFactory.GetShoes("OFFICE");
Console.WriteLine(shoe.GetType()); //Will be office shoes
//Store is ordering the factory to get sports shoes
shoe = ShoeFactory.GetShoes("SPORTS");
Console.WriteLine(shoe.GetType()); //Will be sports shoes
}
}
//This is the factory supplying shoes. It can supply sports shoes or office shoes
//based on demand
class ShoeFactory
{
public static Shoe GetShoes(string strShoeType)
{
switch (strShoeType)
{
case "SPORTS": return new SportShoe();
break;
case "OFFICE": return new OfficeShoe();
break;
default:
return null;
}
}
}
//This is an abstract class representing product family
//In this example, its shoe
public abstract class Shoe
{
}
//Office shoe is a concrete class belongs to shoe family
class OfficeShoe : Shoe
{
}
//Sports shoe is a concrete class belongs to shoe family
class SportShoe : Shoe
{
}
}
El patrón de método de fábrica se puede usar cuando existe la necesidad de generar objetos que pertenecen a una familia específica. Además de este requisito, también debe mantener las decisiones tomadas con respecto a la instanciación de objetos en un solo lugar.
Por favor, consulte el siguiente enlace para más detalles.
http://xeon2k.wordpress.com/2010/11/27/factory-method-pattern/
Es mejor tener un patrón de método de fábrica frente a una palabra clave nueva. La idea es mover una instanciación completa de objetos fuera de la lógica comercial. Este principio es el quid de la inyección de dependencia . Y, el trabajo del método de fábrica se puede delegar en un Marco de inyección de dependencia como Spring.net o Castle Windsor en un momento posterior.
Estoy usando patrones de fábrica cuando
Cuando una clase no sabe qué clase de objetos debe crear.
Una clase especifica sus subclases para especificar qué objetos crear.
En el lenguaje del programador (forma muy cruda), puede usar el patrón de fábrica donde tiene que crear un objeto de cualquiera de las subclases según los datos proporcionados.
Para responder la segunda parte de su pregunta desde mi opinión, creo que la razón por la que es mejor que la palabra clave "nueva" es que el método de fábrica reduce la dependencia de los constructores de clases particulares. Al usar un método de fábrica, usted delega la creación del objeto en cuestión a otra persona, por lo que la persona que llama no necesita el conocimiento de cómo crear el objeto.
Puede consultar la sección 9.5 Fábricas de Framework Design Guidelines 2nd Edition. Aquí está el conjunto de pautas citado con respecto al uso de fábricas sobre constructores:
SI prefieren constructores a fábricas, porque generalmente son más utilizables, consistentes y convenientes que los mecanismos de construcción especializados.
CONSIDERE el uso de una fábrica si necesita más control del que pueden proporcionar los constructores con respecto a la creación de las instancias.
SÍ use una fábrica en los casos en que un desarrollador no sepa qué tipo construir, como cuando se codifica contra un tipo de base o interfaz.
CONSIDERE usar una fábrica si tener un método determinado es la única forma de que la operación se explique por sí misma.
SÍ use una fábrica para operaciones de conversión.
Y de la sección 5.3 Diseño del Constructor
CONSIDERE usar un método de fábrica estático en lugar de un constructor si la semántica de la operación deseada no se asigna directamente a la construcción de una nueva instancia, o si seguir las pautas de diseño del constructor no es natural.
Tengo dos casos en los que tiendo a usarlo:
- El objeto necesita ser inicializado de alguna manera específica
- Cuando quiero construir un tipo específico basado en un tipo abstracto (una clase abstracta o una interfaz).
Ejemplos:
El primer caso podría ser que desee tener una fábrica que cree objetos
SqlCommand
, donde se adjuntará automáticamente unaSqlConnection
válida antes de devolver el objeto de comando.El segundo caso es si tiene una interfaz definida y determina en el momento de la ejecución qué implementación exacta de la interfaz debe usar (por ejemplo, especificándola en un archivo de configuración).
Use el patrón Abstract Factory cuando un sistema debe ser independiente de cómo se crean, componen y representan sus productos. un sistema debe configurarse con una de las múltiples familias de productos. una familia de objetos de productos relacionados está diseñada para usarse en conjunto, y usted necesita imponer esta restricción. desea proporcionar una biblioteca de clases de productos, y desea revelar solo sus interfaces, no sus implementaciones.
Use un método de fábrica (no de fábrica abstracto) cuando desee reutilizar una funcionalidad común con diferentes componentes.
Ejemplo: imagina que tienes un rifle M16. Algo como esto:
public class M16
{
private Scope scope = new StandardScope();
private SecondaryWeapon secondary = new Bayonet();
private Camouflage camo = new DesertCamo();
public double getMass()
{
// Add the mass of the gun to the mass of all the attachments.
}
public Point2D shootAtTarget(Point2D targetPosition)
{
// Very complicated calculation taking account of lots of variables such as
// scope accuracy and gun weight.
}
}
Puede estar satisfecho con esto por un tiempo, pensando que no querrá cambiar nada. Pero luego tienes que hacer una secreta misión nocturna de sigilo en la jungla, y te das cuenta de que tus archivos adjuntos son completamente inapropiados. Realmente necesitas un telescopio NightVision, JungleCamo y un arma secundaria GrenadeLauncher. Tendrás que copiar más allá del código de tu M16 original ... no es una buena extensibilidad ... ¡Método de fábrica para el rescate!
Reescribe tu clase M16:
public abstract class M16
{
private Scope scope = getScope();
private SecondaryWeapon secondary = getSecondaryWeapon();
private Camouflage camo = getCamouflage();
public double getMass()
{
// Add the mass of the gun to the mass of all the attachments.
}
public Point2D shootAtTarget(Point2D targetPosition)
{
// Very complicated calculation taking account of lots of variables such as
// scope accuracy and gun weight.
}
// Don''t have to be abstract if you want to have defaults.
protected abstract Scope getScope();
protected abstract SecondaryWeapon getSecondaryWeapon();
protected abstract Camouflage getCamouflage();
}
//Then, your new JungleM16 can be created with hardly any effort (and importantly, no code //copying):
public class JungleM16 : M16
{
public Scope getScope()
{
return new NightVisionScope();
}
public SecondaryWeapon getSecondaryWeapon()
{
return new GrenadeLauncher();
}
public Camouflage getCamouflage()
{
return new JungleCamo();
}
}
¿Idea principal? Personalice y cambie los objetos de composición mientras mantiene una funcionalidad común.
Un lugar realmente útil para usarlo: acaba de diseñar una interfaz gráfica de usuario realmente genial, y tiene un diseño realmente complicado. Sería un verdadero dolor tener que diseñar todo de nuevo si quisiera tener diferentes widgets. Entonces ... use un método de fábrica para crear los widgets. Luego, si cambia de opinión (o si alguien más quiere usar su clase, pero usa diferentes componentes), puede subclase la GUI y anular los métodos de fábrica.