2008-11-02 12 views
13

Tengo una clase que define un tipo de CallRate. Necesito agregar la capacidad de crear varias instancias de mi clase leyendo los datos de un archivo.¿Debería una clase C# generar instancias de sí mismo?

Agregué un método estático a mi clase CallRate que devuelve List<CallRate>. ¿Está bien para una clase generar nuevas instancias de sí mismo llamando a uno de sus propios constructores? Funciona, solo me pregunto si es lo correcto.

List<CallRates> cr = CallRates.ProcessCallsFile(file); 

Respuesta

20

Está perfectamente bien obtener objetos propios del método estático.

p. Ej.

Una de las bibliotecas de la red del punto hace lo mismo como lo hizo,

XmlReadrer reader = XmlReader.Create(filepathString); 
+0

Esto se llama el patrón de fábrica si no me equivoco y, como se dijo, es un método perfectamente viable para llevar a cabo esa tarea. Por lo general, prefiero mantener la fábrica separada de la clase, pero eso depende en gran medida de las preferencias personales. –

+0

Hay dos tipos de fábrica (en el libro de GoF): Abstract Factory y Factory Method. El método presentado es un ejemplo de método de fábrica. –

+0

Sí, el patrón de fábrica de hecho. –

2

Me parece bien. En otros idiomas probablemente escribirías una función, pero en un lenguaje como C#, los métodos estáticos toman ese rol.

1

Está bien. Lo que acaba de crear es algo así como un simple método de fábrica. Tiene un método estático que crea una instancia válida de un tipo. En realidad, su método ni siquiera tiene que ser estático y aún tiene un código válido. Hay un patrón de diseño (prototipo) que crea un nuevo objeto válido a partir de un objeto existente. Ver detalles en http://www.dofactory.com/Patterns/PatternPrototype.aspx.

+0

Necesitaba una buena razón para comenzar a aprender los patrones de diseño de clase. Gracias. – user10178

1

Claro, para escenarios simples de análisis (o similares) - De hecho, prefiero el factory method sé parte de la clase. Sí, rompe SRP, pero cumple KISS, así que lo llamo ganancia neta. Para aplicaciones más grandes, o rutinas de análisis más complicadas, tiene más sentido que sea una clase de fábrica externa.

para su caso particular, probablemente preferiría un método que tomó en un IEnumerable <cadena> en lugar de un nombre de archivo - que todavía le daría la lógica de análisis, pero permitir pruebas unitarias fáciles y "reutilización". La persona que llama puede envolver el archivo en un IEnumerable con bastante facilidad.

1

Los métodos de fábrica a menudo son un buen diseño. Cuando las escribo en C#, yo los llamo 'Nuevo', de modo que:

new MyClass() 

convierte

MyClass.New() 

Trivialmente se implementa como esto:

class MyClass 
{ 
    public static MyClass New() 
    { 
     return new MyClass(); 
    } 
} 

Parcialmente hago esto cuando hay condiciones adicionales sobre si realmente crear la clase o simplemente devolver null, o si devolver MyClass o algo derivado de él.

+0

Debe ser confuso para las personas que están acostumbradas a VB.Net. En VB.Net, el constructor se llama "Nuevo". – Kibbee

+0

Quizás; o tal vez tenga sentido, piénselo como un ctor estático frente a un ctor de instancia o algo así. Realmente no puedo decirlo, ya que no he dedicado mucho tiempo a los programadores de VB.NET. –

1

A veces uso métodos públicos estáticos como alternativa a la sobrecarga del constructor.

Especialmente en situaciones en las que no es bueno depender únicamente de los tipos de parámetros para indicar qué tipo de construcción de objeto se pretende.

1

Soy un fanático de tener métodos estáticos para devolver instancias, como se sugirió muchas veces, más arriba.

@Paul: no olvide marcar el comentario anterior, que encuentra que es la mejor respuesta.

+0

¡Lo siento! Todos me dieron algo de ayuda, así que puse todo de pie. No tengo la reputación de eliminar tics marcando y simplemente elegir uno. boneHead = me; – user10178

+0

Se eliminan "up-ticks" al presionarlos por segunda vez –

1

al igual que señalar "generar nuevas instancias de sí mismo llamando a uno de sus propios constructores"

No es por el constructor, es a partir del método estático.

+0

Sí, pero mi método estático está llamando a uno de sus constructores ... De hecho, he descubierto que es su propia clase ahora. Gracias. – user10178

1

Generalmente uso esto cuando necesito implementaciones instantáneas de una clase. Por ejemplo

public class Car 
    { 
     public static Car RedExpensiveCar = new Car("Red", 250000); 

     public Car() 
     { 

     } 

     public Car(string color, int price) 
     { 
      Color = color; 
      Price = price; 
     } 

     public string Color { get; set; } 
     public int Price { get; set; } 
    } 

Y con esto, no necesito recordar ni escribir parámetros de constructor en mi código.

Car car = Car.RedExpensiveCar; 
+0

Tenga en cuenta que en su ejemplo, Car car = Car.RedExpensiveCar * no * crea un automóvil nuevo. Siempre devolverá la misma instancia. Aún más problemático, ya que está utilizando un campo público, podría asignarse a: Car.RedExpensiveCar = new Car ("Primer Brown", 75); – munificent

+0

Generalmente mejor es público estático Car RedExpensiveCar {get {return new Car ("Red", 250000); }} – munificent

3

A menudo uso este patrón cuando necesito verificar la validez de los parámetros. Se desaconseja encarecidamente lanzar una excepción desde un constructor. No es tan malo desde un método de fábrica, o puede elegir devolver nulo.

0

Es perfectamente aceptable hacerlo. Cuando lo hago, normalmente hago que los constructores reales para la clase sean privados, por lo que está claro que la forma solo de construir instancias es a través del método estático.

Esto es muy útil en los casos en que "construcción" no siempre devuelve una nueva instancia. Por ejemplo, es posible que desee devolver un objeto previamente almacenado en caché.

Cuestiones relacionadas