2010-01-26 14 views
8

Los patrones de Singleton y del Registro fueron muy simples y fáciles de entender para mí, pero el patrón de Factory ha sido algo que aún no he podido hacer que mi cerebro interprete al 100%. Creo que puedo entenderlo ahora. He escrito un código de muestra a continuación, por favor revíselo y dígame si este es el uso correcto del patrón de fábrica. Muestra está en PHP ...¿Es así como funciona el patrón de fábrica?

<?php 
/** 
* Factory.class.php 
*/ 
class Factory { 
    public static $_database; 
    public static $_cache; 
    public static $_session; 

    // Build our User object with all it's dependencies 
    public static function makeUserObject() 
    { 
     $user = new User(); 
     $user->setDatabaseObject(self::$_database); 
     $user->setCacheObject(self::$_cache); 
     $user->setSessionObject(self::$_session); 
     return $user; 
    } 

    // other objects will be here someday...... 
} 

/** 
* User.class.php 
*/ 
class User 
{ 
    public function __construct() { } 

    // inject Database Object 
    public function setDatabaseObject($databaseConnectionObject) 
    { 
     $this->_databaseObject = $databaseConnectionObject; 
    } 

    // inject Cache Object 
    public function setCacheObject($cacheObject) 
    { 
     $this->_cacheObject = $cacheObject; 
    } 

    // inject Session Object 
    public function setSessionObject($sessionObject) 
    { 
     $this->_sessionObject = $sessionObject; 
    } 

    // other methods here for User object........... 
} 

/** 
* index.php Main page that puts it all together 
* assume that classes are autoloaded into this page already 
*/ 
// Set our Database + Cache + Session objects into the Factory Object 
Factory::$_database = new Databse(); 
Factory::$_cache = new Cache(); 
Factory::$_session = new Session(); 

// Create our User object 
// The factory class will build the User object and inject all 
// it's dependencies for us =) 
$user = Factory::makeUserObject(); 

?> 

Así que, básicamente, la base de datos, caché, y los objetos de sesión se crean (no se muestra aquí), entonces se añaden al objeto de fábrica, que la puede construir un método en la clase de fábrica para cada objeto que necesitará cualquiera de estas 3 dependencias y también puedo establecer cuáles obtienen. Esto también hace que las clases individuales todavía puedan ser algo portátiles ya que puedo inyectar allí dependencias directamente si quisiera sin el objeto de fábrica. Suena bien? Si esto es correcto, esto suena realmente útil


ACTUALIZACIÓN # 1

Esto se basa de esto aquí un post que leí aquí http://www.potstuck.com/2009/01/08/php-dependency-injection/ se refieren a ella como una "fábrica", he estado usando un Registro y mucha gente sigue diciéndome que investigue una "fábrica" ​​y todo lo que leí al respecto simplemente no hizo clic en mi cabeza hasta que leí este artículo, pero parece que no es una "fábrica".


ACTUALIZACIÓN # 2
De wikipedia http://en.wikipedia.org/wiki/Factory_object En la programación informática orientada a objetos, un objeto de fábrica es un objeto para la creación de otros objetos. Es una abstracción de un constructor y se puede usar para implementar varios esquemas de asignación, como el patrón singleton. Un objeto de fábrica generalmente tiene un método para cada tipo de objeto que es capaz de crear. Estos métodos aceptan opcionalmente parámetros que definen cómo se crea el objeto y luego devuelven el objeto creado. Los objetos de fábrica se usan en situaciones en las que agarrar un objeto de un tipo particular es un proceso más complejo que simplemente crear un objeto nuevo. El objeto de fábrica puede decidir crear la clase del objeto (si corresponde) dinámicamente, devolverlo desde un grupo de objetos, realizar una configuración compleja en el objeto u otras cosas.

así que quizás es un "objeto de fábrica" ​​de una manera después de todo ...

+0

¿Puede proporcionar una fuente que describe este patrón 'de fábrica'? Sé de patrones llamados 'Abstract Factory' y 'Factory Method', pero no solo 'Factory'. –

+0

@Gordon wow eso es un montón de patrones! Así que supongo que esto no es realmente una fábrica, y pensé que finalmente estaba en algo bueno aquí – JasonDavis

+0

@Gordon: Sí, esos son los patrones de creación del libro GoF :) No hay patrón 'Factory' allí ... –

Respuesta

6

Resumido y extendieron mis comentarios desde abajo la pregunta aquí

Al igual que otros dijeron, no es una fábrica , simplemente porque un patrón con este nombre no existe. Es AbstractFactory o FactoryMethod, aunque las personas pragmáticamente a menudo se refieren a cualquiera o simplemente diciendo Factory y eso está bien conmigo.

La sesión, la caché y la base de datos suelen ser algo que se inicializará temprano en el flujo de la aplicación, por lo que básicamente se trata de un trabajo de arranque. Me da la impresión de que lo que está buscando no es tanto la creación de objetos, sino su manejo en toda la aplicación. Esa es una preocupación un tanto diferente de lo que hace un FactoryWhatever.

Como dije en los comentarios, simplemente porque no es exactamente una FactoryWhatever, no significa que su código sea incorrecto. Si resuelve tu problema, es genial. Pero aún pienso, lo que estás tratando de hacer, p. crear y administrar recursos en tiempo de ejecución es mejor usarlo con un DIContainer.

Si no desea utilizar un contenedor DI ahora para esto, puede echar un vistazo a Zend_Application and how they bootstrap resources. Es una alternativa y deja la posibilidad de add DI containers later.

De hecho, bastantes de los temas en sus preguntas anteriores ya se han resuelto en Zend Framework, p. Clases de configuración No estoy diciendo usar ZF, pero podrían verificarlo para ver cómo hacen las cosas. Por supuesto, puede mirar el otherframeworks también.

Algunos sitios de patrones con ejemplos de PHP:

+0

Gracias por los enlaces que estaba leyendo esta página http://en.wikipedia.org/wiki/Factory_object y suena como lo que estoy pasando en el código anterior, leeré los enlaces que proporcionó sin embargo, mi proyecto está básicamente en espera hasta que encuentre el mejor enfoque para todo esto, quiero hacerlo bien la primera vez o lo mejor que pueda de todos modos – JasonDavis

+0

Creo que no se puede * hacerlo bien * desde el principio. Pensar en el futuro está bien (y es necesario), pero también lo es usar lo que funciona hasta que ya no funciona y luego refactorizar. – Gordon

1

se parece más a la Builder para mí. ¿Qué patrón de fábrica realmente quiso decir, AbtractFactory o FactoryMethod? Sin embargo, ambos se ocupan de la herencia y tu código solo ensambla un objeto "complejo".

+0

Esto se basa en esto aquí http: // www .potstuck.com/2009/01/08/php-dependency-injection/No estoy muy seguro, he estado usando un registro y mucha gente sigue diciéndome que investigue una "fábrica" ​​y todo lo que leo al respecto simplemente no hizo clic en mi cabeza hasta que leí este artículo – JasonDavis

+0

El artículo discutido trata de inyección de dependencia no en fábricas. Admito que el término Fábrica a veces se usa para diferentes propósitos. Pero definitivamente este no es uno de los patrones de fábrica en el libro de GoF. – bertolami

3

does't vea como una fábrica para mí - podría ser un constructor de adentro hacia afuera; 0)

Factory es una forma de ocultar la implementación y creación de instancias?. Y por lo general hay un poco de montaje está hecho, pero en pocas palabras ....

public interface IUser 
    { 
     void DoSomething(); 
    } 

    public class DumbUser : IUser 
    { 

     public void DoSomething() 
     { 
      // duh... what should i do? 
     } 

    } 

    public class SmartUser : IUser 
    { 

     public void DoSomething() 
     { 
      // calclulating prime numbers while baking bread 
     } 

    } 


    public class UserFactory 
    { 
     public static IUser CreateUser() 
     { 
      Random r = new Random(Environment.TickCount); 

      return r.Next(10) > 5 ? (IUser) new SmartUser() : new DumbUser(); 
     } 
    } 

    public class YourProgram 
    { 
     public void Run() 
     { 
      IUser user = UserFactory.CreateUser(); 
      user.DoSomething(); 
     } 
    } 
+0

+1 Sin cuidado, rasgado y pegado en mis notas de diseño. Primera implementación sensible de php que tengo de este patrón. Gracias amigo. – stefgosselin

2

Puesto que parece que simplemente desea crear un usuario, no veo la necesidad de un factor abstracto, en adelante denominado simplemente para como fábrica. La idea de las fábricas es crear objetos que implementen una determinada interfaz. Te gustaría poder instanciar dos implementaciones diferentes de la misma interfaz. El punto es que puede que tenga que crear estos objetos una y otra vez, y cambiarlo de ObjectA a ObjectB todo el código es engorroso. El intercambio de la fábrica es fácil, porque a menudo es un singleton.La idea del método de fábrica está relacionada con los marcos: Desea crear un uso en algún código de marco, pero la implementación real del usuario está en clases derivadas, es decir, hay usuarios de su marco escribiendo su propia aplicación, es decir, necesita decirle al usuario de su marco "crear un objeto de usuario ahora", que es una llamada al método de fábrica. El usuario debe implementar esto. También se llama Contstructor Virtual según GoF.

El constructor se usa generalmente cuando hay diferentes representaciones del objeto, lo que no es realmente el caso aquí. En mi opinión, el caché, la base de datos y la sesión podrían implementarse como singleton, lo que facilitaría las complejidades involucradas. De lo contrario, sugeriría usar un ServiceLocator que le permite GetDatabase, GetSession, etc. Luego, tendría que pasar el localizador al objeto de usuario (y muchos otros objetos) en la creación. Lo bueno es que este localizador se puede reutilizar en diferentes clases.

+0

Este localizador del que hablas parece más como lo que estoy buscando. Actualmente estoy almacenando una referencia a objetos como sesión, base de datos, caché dentro de un registro en este momento y luego inyectar el registro en otros objetos en la creación, ¿es eso similar? – JasonDavis

+0

Creo que sí, esencialmente. Le sugiero que lea estos dos artículos de Martin Fowler: http://martinfowler.com/articles/injection.html http://martinfowler.com/eaaCatalog/registry.html lo explica en gran detalle y mejor que yo, también creo que 500 caracteres no harán el trabajo :) Además, es posible que desee obtener una copia de su libro "Patrones de arquitectura de aplicaciones empresariales" vale la pena cada centavo. En general, diría que la Inversión de Control y la Inyección de Dependencia son más complejas que los patrones básicos, uno de los cuales es el patrón de fábrica por lo que esto lo lleva mucho más allá de su OQ. – mnemosyn

5

Ese es el patrón de fábrica correcto, pero es posible que necesite una mejor convención de nombres que simplemente llamarlo Factory. También contiene trazas de inyección de dependencia.

Aunque técnicamente podría llamarse patrón de fábrica, probablemente no sea un buen uso del patrón. Factory es un patrón creacional que encapsula su código para que haga referencia directa a nombres de clases y creación de objetos como en los parámetros exactos del constructor, etc. Para obtener los mejores resultados, téngalo en cuenta al diseñar sus clases y fábricas.

Por ejemplo, StackOverflow otorga a los usuarios diferentes derechos según su reputación. Hipotéticamente hablando, podría tener los siguientes tipos de usuarios:

NewbieUser  [1-100] 
BeginnerUser [101-1000] 
AverageJoeUser [1001-5000] 
VeteranUser  [5001-20000] 
PowerUser  [20001-50000] 
GodModeUser  [50001-100000] 

y un usuario puede ser creado por buscar su representante. y crear instancias del objeto de usuario correspondiente al hacer referencia directamente a la clase. Jon Skeet no aparece en ninguna categoría en caso de que te lo estés preguntando. He aquí una aplicación de mierda con instanciación directa:

if(reputation >= 1001 and reputation <= 5000) { 
    AverageJoeUser user = new AverageJoeUser(); 
} 

Si más adelante en el camino que debíamos cambiar los nombres de las clases o la forma en que los usuarios se instanciado, cada uno de esos caso en que el objeto fue creado tendría que ser encontrado y cambiado. Mucho trabajo si me preguntas. En cambio, si hubiésemos utilizado el patrón Factory aquí, el cambio iría en un único método dentro de la clase Factory.

class UserFactory { 
    public static User createUser(Integer reputation) { 
     ... 
    } 
} 
+0

Tengo que decir que me encantan los "nombres de clasificación hipotéticos", ¡tendré que guardarlos para clasificarlos en un foro futuro que estoy planeando! – JasonDavis

+0

¿Eso significa que Jon Skeet está por encima de Dios? –

+0

@jason, esa podría ser una excelente manera de alejar a los usuarios activos de su sitio :) – Anurag

Cuestiones relacionadas