Pregunta

Digamos que tengo una clase como esta:

class MonkeyFish
{
   MonkeyFish( GlobalObjectA & a, GlobalObjectB & b, GlobalObjectC & c);

   private:
     GlobalObjectA & m_a;
     GlobalObjectB & m_b;
     GlobalObjectC & m_c;
}

Sin una fábrica, tengo que hacer lo siguiente para crear una instancia de MonkeyFish .

GlobalObjectA a;
GlobalObjectB b;
GlobalObjectC c;

int main()
{
  MonkeyFish * monkey_fish = new MonkeyFish(a, b, c);
  monkey_fish->go();
}

Por otro lado, si tengo un MonkeyFishFactory , parece que tengo que hacer esto:

GlobalObjectA a;
GlobalObjectB b;
GlobalObjectC c;

int main()
{
  MonkeyFishFactory mf_factory(a, b, c);
  MonkeyFish * monkey_fish = mf_factory.buildMonkeyFish("Bob");
  monkey_fish->go();
}
  1. Todavía tengo objetos globales.

  2. Incluso si el propio MonkeyFishFactory creó el GlobalObjects internamente (por lo que ahora están dentro del MonkeyFishFactory en lugar de los verdaderos globales), parece que el MonkeyFishFactory en sí mismo todavía está debe ser un objeto global para que pueda acceder a él en cualquier momento que quiera crear un MonkeyFish.

¿No es el patrón de Fábrica lo mismo que el estado global en este caso?

(Actualmente estoy operando bajo el supuesto de que el estado global es una Cosa Mala, y eliminarlo es una Cosa Buena).

¿Fue útil?

Solución

¿Estás confundiendo conceptos aquí?

El patrón de Fábrica generalmente se aplica cuando está devolviendo una instancia de una clase concreta que se esconde detrás de una interfaz abstracta. La idea es que la persona que llama verá solo la interfaz y ni siquiera tiene que saber cuál es el tipo concreto del objeto. Se trata de crear una instancia de objeto basada en parámetros y desacoplar la lógica asociada a decidir qué objeto crear desde el usuario que crea el objeto.

Lo que estás describiendo es una mezcla de Singleton (o MonoState) y Factory. Tu Fábrica tiene un estado por lo que no puede hacerse estática. En este caso, deberá aplicar algo como el patrón de Singleton para controlar la creación de una única instancia de Factory con los globales adecuados ocultos dentro de ella:

class IMonkeyFish {
public:
    virtual ~IMonkeyFish() = 0;
    virtual void go() = 0;
};

class Factory {
public:
    static Factory& instance();
    IMonkeyFish* createMonkeyFish();
protected:
    Factory(GlobalObjectA& a, GlobalObjectB& b, GlobalObjectC& c);
private:
    static Factory *theInstance;
    GlobalObjectA&  instanceOfA;
    GlobalObjectB&  instanceOfB;
    GlobalObjectC&  instanceOfC;
};

Factory& factory = Factory::instance();
IMonkeyFish* fishie = factory.createMonkeyFish();
fishie->go();

El patrón Singleton gobierna la creación de la instancia de fábrica. El patrón Factory oculta los detalles que rodean la creación de objetos que implementan la interfaz IMonkeyFish . The Good Thing (TM) es la ocultación del estado global y el desacoplamiento de los detalles concretos de MonkeyFish para crear una instancia.

El uso o la corrección de usar el Singleton es un problema completamente distinto. Probablemente hay un montón de hilos flotando alrededor de eso también.

Otros consejos

El estado global no es en sí mismo una Cosa Mala. Público El estado global es una cosa mala. El patrón de Fábrica ayuda a encapsular el estado global, lo cual es bueno.

No hay un estado global en la Fábrica. Simplemente crea objetos. Como no hay ningún estado en la fábrica. Está bien ser global.

No tienes que dejar objetos globales. La fábrica de peces mono debería crear esos GlobalOjectA | B | C a pedido. Usando el interruptor o si está dentro del método para determinar cuál.

Usted tiene control encapsulado sobre la creación de objetos en una fábrica. Desea que los detalles de su instanciación se oculten, no se reproduzcan en todos los lugares donde necesite un nuevo MonkeyFish. Piensa en las pruebas, la responsabilidad única y la ley de Demeter. ¿Por qué su clase que quiere usar un MonkeyFish debe saber algo sobre el trabajo que se necesita para construir uno? ¿Qué pasa si quieres probar MonkeyFish? ¿Cómo lo haría si no tuviera los detalles de la creación encapsulados?

El trabajo de una clase de fábrica es crear una instancia de un objeto y devolverlo a la persona que llama; No elegir qué objeto instanciado global usar. Por lo tanto, su ejemplo de fábrica es incorrecto. Debería ser:

int main()
{
  MonkeyFish * monkey_fish = MonkeyFishFactory::buildMonkeyFish("Bob");
  monkey_fish->go();
}

Observe, no hay objetos globales, y MonkeyFishFactory no se crea una instancia.

Creo que estás pensando en el patrón Singleton, no en el patrón de fábrica. En el patrón de singleton solo tienes una instancia de una clase que básicamente lo hace equivalente a un objeto global, excepto que no hay una variable global adjunta.

Debe indicar sus limitaciones y requisitos si desea obtener una buena respuesta. Lo más importante para obtener una buena respuesta es saber qué pregunta hacer.

En los fragmentos de código que proporcionaste, decidiste usar globales, pero eso no tiene nada que ver con si usas una Factory o no. Si utilizas una fábrica que aún depende de esos globales, solo tienes otro código para acumular el resto.

Intente indicar claramente lo que está tratando de lograr y probablemente obtendrá una mejor respuesta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top