method - patron factory c#
Patrón de fábrica para construir muchas clases derivadas (3)
Estás "descentralizando" la fábrica, de modo que cada subclase es responsable de crearse a sí misma.
Más comúnmente tendrías una fábrica central que sabría sobre los posibles subtipos y cómo construirlos (con frecuencia, simplemente creando una nueva instancia y devolviendo esa instancia escrita como una interfaz común o clase base común). Ese enfoque evita el problema que tiene actualmente. Tampoco veo ningún beneficio para su enfoque actual. Actualmente no obtiene encapsulación ni reutilización de código en comparación con la implementación más típica de una fábrica.
Para referencia adicional, eche un vistazo a
Tengo un objeto de fábrica ChallengeManager
para generar instancias de un objeto Challenge
para un juego que estoy construyendo. Hay muchos desafíos Los constructores para cada derivación de la clase Challenge
son diferentes, sin embargo, existe una interfaz común entre ellos, definida en la clase base.
Cuando llamo a manager.CreateChallenge()
, devuelve una instancia de Challenge
, que es uno de los tipos derivados.
Idealmente, me gustaría mantener el código para la construcción del objeto dentro de la misma clase derivada, de modo que todo el código relacionado con ese objeto esté ubicado en el mismo lugar. Ejemplo:
class Challenge {}
class ChallengeA : Challenge {
public static Challenge MakeChallenge() {
return new ChallengeA();
}
}
class ChallengeB : Challenge {
public static Challenge MakeChallenge() {
return new ChallengeB();
}
}
Ahora, mi llamada a ChallengeManager.CreateChallenge()
solo necesita decidir en qué clase convocar a MakeChallenge()
. La implementación de la construcción está contenida por la clase misma.
Usando este paradigma, cada clase derivada debe definir un MakeChallenge()
estático MakeChallenge()
. Sin embargo, dado que el método es estático, no puedo usar una interfaz aquí, que lo requiera.
No es gran cosa, ya que puedo recordar fácilmente agregar la firma de método correcta a cada clase derivada. Sin embargo, me pregunto si hay un diseño más elegante que debería considerar.
Me gusta mucho el patrón que describes y lo uso a menudo. La forma en que me gusta hacerlo es:
abstract class Challenge
{
private Challenge() {}
private class ChallengeA : Challenge
{
public ChallengeA() { ... }
}
private class ChallengeB : Challenge
{
public ChallengeB() { ... }
}
public static Challenge MakeA()
{
return new ChallengeA();
}
public static Challenge MakeB()
{
return new ChallengeB();
}
}
Este patrón tiene muchas buenas propiedades. Nadie puede hacer un nuevo Challenge
porque es abstracto. Nadie puede hacer una clase derivada porque el ctor predeterminado de Challenge
es privado. Nadie puede llegar a ChallengeA
o ChallengeB
porque son privados. Usted define la interfaz para Challenge
y esa es la única interfaz que el cliente debe comprender.
Cuando el cliente quiere una A
, le piden a Challenge
uno, y la obtienen. No necesitan preocuparse por el hecho de que detrás de las escenas, A
está implementado por ChallengeA
. Simplemente obtienen un Challenge
que pueden usar.
No necesariamente la respuesta que está buscando pero ... Puede usar la siguiente implementación, si puede alejarse del método estático por clase.
using System;
public class Test
{
public static void Main()
{
var c1 = ChallengeManager.CreateChallenge();
var c2 = ChallengeManager.CreateChallenge();
//var c = ChallengeManager.CreateChallenge<Challenage>(); // This statement won''t compile
}
}
public class ChallengeManager
{
public static Challenage CreateChallenge()
{
// identify which challenge to instantiate. e.g. Challenage1
var c = CreateChallenge<Challenage1>();
return c;
}
private static Challenage CreateChallenge<T>() where T: Challenage, new()
{
return new T();
}
}
public abstract class Challenage{}
public class Challenage1: Challenage{}
public class Challenage2: Challenage{}