tipos sobreescribir que programacion polimorfismo instancias declaracion constructores c# oop coding-style constructor

c# - sobreescribir - Fábrica vs constructores instancia



sobreescribir constructor c# (10)

Puedes curry métodos de fábrica. Tratar de curry un constructor te da: un método de fábrica.

Uso esto en algunos de mis códigos que enumeran el árbol Administrador de dispositivos de Windows. Una de las clases enumera los puertos seriales, cada puerto serie tiene una propiedad de fábrica de conexión que devuelve un método de fábrica al curry con la dirección del puerto (cadena de dispositivo PNP realmente fea) almacenada en estado interno mientras se proporcionan la velocidad en baudios, bits de parada y paridad luego.

No puedo pensar en ninguna razón por la cual uno es mejor que el otro. Compare estas dos implementaciones:

public class MyClass { public MyClass(string fileName) { // some code... } }

Opuesto a:

public class MyClass { private MyClass(){} public static MyClass Create(string fileName) { // some code... } }

Hay algunos lugares en el marco .Net que usan un método estático para crear instancias. Al principio estaba pensando, registra instancias para hacer un seguimiento de ellos, pero los constructores regulares podrían hacer lo mismo mediante el uso de variables privadas estáticas.

¿Cuál es el razonamiento detrás de este estilo?


A veces es importante llevar contabilidad y / o administración de recursos para cada instancia de una clase creada. Como resultado, es importante que cada construcción se administre globalmente y un método estático para hacer la construcción lo hará muy bien.


Como puede ver, myClass no sigue un patrón de fábrica "clásico" (donde la clase de la instancia no se conoce / se expone fuera de la fábrica).

Sin embargo, en este caso, el equipo .NET Framework puede no estar apuntando a un patrón de fábrica, pero supongo que no quieren que acabes de actualizar la clase objetivo directamente con un nombre de archivo a través de un constructor. Una fábrica puede ser excesiva si solo se proporciona esta clase.

Este patrón se ve a veces en métodos clone (), donde un objeto puede devolver una instancia que es una especie de duplicado de sí mismo.

Además, aunque la clase sea pública, es posible que deseen realizar algunas comprobaciones con la creación de instancias, el nombre de archivo, etc., y si implementaron una fábrica, la clase objetivo aún podría crearse e invocarse, evitando los controles.


El método de Create estático puede crear instancias y devolver:

  • Una instancia de MyClass
  • Una instancia de cualquier subclase de MyClass
  • null

El método de fábrica a menudo se usa para ocultar el tipo exacto del objeto que se está creando. Una clase abstracta puede tener un método de fábrica estático, que luego selecciona la clase derivada concreta para crear instancias dependiendo de alguna condición. Solo la clase base abstracta está documentada públicamente. Esto deja al proveedor de la biblioteca algo de libertad para cambiar el tipo exacto que se crea una instancia sin romper el código existente.

Un ejemplo del framework .NET son los métodos estáticos de fábrica en la clase Expression .


Estuve investigando este punto y encontré esta pregunta, pero no creo que haya sido respondida completamente. Sin embargo, sí encontré este práctico artículo - Actualización de Lineamientos de Diseño: Fábricas vs. Constructores - por Krzysztof Cwalina (Arquitecto Principal en el Marco .NET). Vale la pena leer todo el artículo, pero aquí hay un breve resumen de los puntos principales:

La forma más común y consistente de crear una instancia de un tipo es a través de su constructor. Sin embargo, a veces una alternativa preferible es usar el patrón de fábrica.

Prefiere los constructores sobre las fábricas, ya que generalmente son más consistentes y convenientes que los mecanismos de construcción especializados.

Implemente las operaciones de fábrica como métodos, no como propiedades.

Devuelve instancias como valores de retorno de método, no como parámetros de salida.

Considere usar Factory si necesita más control sobre los patrones de creación de las instancias.

Considere nombrar métodos de Fábrica concatenando "Crear" y el nombre del tipo que se está creando.

Considere nombrar tipos de Fábrica concatenando el nombre del tipo que se está creando y "Fábrica".

No implemente su fábrica utilizando un método estático si la operación de construcción debe estar disponible para que las subclases se especialicen.

Use una fábrica para operaciones de estilo de conversión.

Use una fábrica si una operación requiere información de parámetros que no se ve natural pasar a un constructor.

No use una fábrica en situaciones en las que la operación de creación se utilizará como escenario central para la creación de instancias de un tipo. En estas situaciones, la detectabilidad y la coherencia son primordiales.

Considere usar un constructor en lugar de una fábrica. Solo después de este proceso de pensamiento debe proceder con la implementación de una fábrica.

Las fábricas también son útiles para permitir la especialización de tipos a través del polimorfismo.

Utilice Factory si los usuarios de la API codificarán en una clase base o interfaz cuya implementación está sujeta a cambios a lo largo del tiempo.

Utilice métodos Factory en los casos en que un desarrollador no sepa qué tipo construir, por ejemplo cuando codifica contra un tipo de base o interfaz.

Implemente las operaciones de fábrica como métodos de instancia virtual en lugar de estáticos si deben admitir la extensión polimórfica.

Utilice el patrón de Singleton para fábricas basadas en instancias para no forzar a los desarrolladores a crear instancias de un tipo de fábrica solo para invocar a uno de sus miembros.

Utilice un método de Fábrica si un constructor sería insuficiente para describir la operación que se está realizando, y la información adicional obtenida de una Fábrica con nombre individual hace que el propósito de una operación sea más claro.


Los métodos que hacen la construcción para usted son muy útiles para:

public class Class { public static List<Class> FromFiles(IEnumerable<String> paths) { List<Class> instances = new List<Class>(); foreach (string path in paths) { instances.Add(new Class() { Path = path }); } return instances; } public string Path { get; set; } }

... ya que los constructores "normales" no pueden hacer esto.


Nota: Lo que tienes no es un constructor estático, es una función estática que crea la instancia en lugar de llamar al constructor de la instancia por ti mismo. Un constructor estático es una cosa completamente diferente.

El patrón de fábrica es un ejemplo clásico del uso de una función (estática o no) para instanciar un tipo en lugar de usar el constructor directamente. Tenga en cuenta que el constructor de instancia real se llamará sin importar qué, pero la función estática proporciona una capa de indirección que le permite devolver una instancia de cualquier tipo que sea o herede del tipo de devolución, en lugar de solo las instancias que son la devolución. tipo.

Por ejemplo:

public abstract class BaseClass { public static BaseClass Create(int parameter) { if (parameter == 1) { return new Class1(); } else { return new Class2(); } } } internal class Class1 : BaseClass { //code here ... } internal class Class2 : BaseClass { //code here ... }

Esto le permite ocultar Class1 y Class2 de ensamblajes externos al tiempo que le permite al consumidor ocuparse de algo especializado.


No derramar la dependencia a los ensamblajes que refieren a su ensamblaje es otra razón.
Parece que si se llama a un constructor para una clase en otro ensamblaje, se requerirá su ensamblaje para hacer referencia a todos los ensamblajes que definen cualquiera de los tipos utilizados por cualquier sobrecarga. Puede solucionar esta dependencia forzada utilizando métodos de fábrica con nombres diferentes.

Ejemplo:

Assembly1.dll (requiere ref a BarAssembly.dll no tan obvio)
class Class1 { void Main(){ var foo = new Foo(); } }

Assembly2.dll (no es necesario hacer referencia a BarAssembly.dll aquí, ya que CreateFoo y CreateFooWithBar no son sobrecargas)
class Class2 { void Main(){ var foo = CreateFoo(); } }

FooAssembly.dll (requiere una referencia a BarAssembly.dll obvio)
class Foo { public CreateFoo(){ ... } public CreateFooWithBar(Bar bar){ ... } public Foo(){ ... } public Foo(Bar bar){ ... } }

BarAssembly.dll
class Bar { public Bar(){ ... } }

Nota: Observado en el edificio VS2013 contra .NET Framework 4.5


Otro caso común donde los métodos de fábrica ayudan (en lenguajes como C # que no admiten la inferencia de tipo del constructor ) es cuando se tiene que minimizar la especificación del parámetro de tipo. Considere el caso común de la clase Tuple . Usted puede hacer:

new Tuple<int, int>(1, 1); //constructor call

o

Tuple.Create(1, 1); //factory pattern.