stringtranslate.com

Patrón de método de fábrica

En la programación orientada a objetos , el patrón de método de fábrica es un patrón de creación que utiliza métodos de fábrica para abordar el problema de crear objetos sin tener que especificar su clase exacta . En lugar de llamar a un constructor , esto se hace llamando a un método de fábrica para crear un objeto. Los métodos de fábrica pueden especificarse en una interfaz e implementarse mediante clases secundarias, o implementarse en una clase base y, opcionalmente, anularse mediante clases derivadas .

Descripción general

El patrón de diseño Factory Method [1] es uno de los veintitrés patrones de diseño conocidos que describen cómo resolver problemas de diseño recurrentes para diseñar software orientado a objetos flexible y reutilizable, es decir, objetos que son más fáciles de implementar, cambiar y probar. y reutilizar.

El patrón de diseño Factory Method resuelve problemas como:

El patrón de diseño Factory Method describe cómo resolver dichos problemas:

Esto permite la escritura de subclases que pueden cambiar la forma en que se crea un objeto (por ejemplo, redefiniendo qué clase crear una instancia).
Consulte también el diagrama de clases UML a continuación.

Definición

"Defina una interfaz para crear un objeto, pero deje que las subclases decidan qué clase crear una instancia. El método Factory permite que una clase difiera la creación de instancias que utiliza a las subclases". ( Pandilla de cuatro )

La creación de un objeto a menudo requiere procesos complejos que no son apropiados para incluirlos en un objeto de composición. La creación del objeto puede dar lugar a una duplicación significativa de código, puede requerir información a la que no puede acceder el objeto que lo compone, puede no proporcionar un nivel suficiente de abstracción o puede no ser parte de las preocupaciones del objeto que lo compone . El patrón de diseño del método de fábrica maneja estos problemas definiendo un método separado para crear los objetos, que las subclases pueden luego anular para especificar el tipo derivado de producto que se creará.

El patrón del método de fábrica se basa en la herencia, ya que la creación de objetos se delega a subclases que implementan el método de fábrica para crear objetos. [2] Como se muestra en el ejemplo de C# a continuación, el patrón del método de fábrica también puede depender de una interfaz, en este caso IPerson, para implementarse.

Estructura

diagrama de clases UML

Un diagrama de clases UML de muestra para el patrón de diseño Factory Method. [3]

En el diagrama de clases UML anterior , la clase que requiere un objeto no crea una instancia de la clase directamente. En cambio, se refiere a un objeto de producto separado para crear, lo que lo hace independiente de qué clase concreta se instancia. Las subclases de pueden redefinir qué clase crear una instancia. En este ejemplo, la subclase implementa lo abstracto creando una instancia de la clase.CreatorProductProduct1CreatorfactoryMethod()CreatorCreatorCreator1factoryMethod()Product1

Ejemplos

Esta implementación de C++14 se basa en la implementación anterior a C++98 del libro. [4]

#incluir <iostream> #incluir <memoria>  enum ProductId { MÍO , TUYO };   // define la interfaz de los objetos que crea el método de fábrica. clase Producto { público : virtual void print () = 0 ; virtual ~ Producto () = predeterminado ; };           // implementa la interfaz del Producto. clase ProductoConcretoMINA : producto público { público : void print () { std :: cout << "this=" << this << " print MINE \n " ; } };               // implementa la interfaz del Producto. clase ProductoConcretoTUYO : producto público { público : void print () { std :: cout << "this=" << this << " print TUYO \n " ; } };               // declara el método de fábrica, que devuelve un objeto de tipo Producto. clase Creador { público : virtual std :: Unique_ptr < Producto > crear ( ProductId id ) { if ( ProductId :: MINE == id ) return std :: make_unique < ConcreteProductMINE > (); if ( ProductId :: TUYO == id ) return std :: make_unique < ConcreteProductYOURS > (); // repetir para los productos restantes...                     devolver nulo ; } virtual ~ Creador () = predeterminado ; };      int main () { // Unique_ptr evita pérdidas de memoria. std :: Unique_ptr < Creador > creador = std :: make_unique < Creador > (); std :: Unique_ptr < Producto > producto = creador -> crear ( ProductId :: MÍO ); producto -> imprimir ();             producto = creador -> crear ( ProductId :: TUYO ); producto -> imprimir (); }   

La salida del programa es como

this = 0x6e5e90 imprime el MIO this = 0x6e62c0 imprime EL TUYO    

Un juego de laberinto se puede jugar en dos modos, uno con salas normales que solo están conectadas con salas adyacentes y otro con salas mágicas que permiten a los jugadores ser transportados al azar.

Estructura

Roomes la clase base para un producto final ( MagicRoomo OrdinaryRoom). MazeGamedeclara el método de fábrica abstracto para producir dicho producto base. MagicRoomy OrdinaryRoomson subclases del producto base que implementa el producto final. MagicMazeGamey OrdinaryMazeGameson subclases de MazeGameimplementación del método de fábrica que produce los productos finales. Por tanto, los métodos de fábrica desacoplan a los llamadores ( MazeGame) de la implementación de las clases concretas. Esto hace que el "nuevo" Operador sea redundante, permite respetar el principio Abierto/cerrado y hace que el producto final sea más flexible en caso de cambio.

Implementaciones de ejemplo

C#

// Vocabulario vacío del objeto real interfaz pública IPerson { string GetName (); }    clase pública Aldeano : IPerson { cadena pública GetName () { return "Persona de la aldea" ; } }           clase pública PersonaCiudad : IPerson { cadena pública GetName () { retorno "Persona de la ciudad" ; } }           enumeración pública Tipo de persona { Rural , Urbano }    /// <summary> /// Implementación de Factory: se utiliza para crear objetos. /// </summary> clase pública PersonFactory { IPerson pública GetPerson ( tipo PersonType ) { switch ( tipo ) { case PersonType . Rural : devolver nuevo aldeano (); caso TipoPersona . Urbano : devuelve nueva CityPerson (); predeterminado : lanzar nueva NotSupportedException (); } } }                          

En el código anterior puedes ver la creación de una interfaz llamada IPersony dos implementaciones llamadas Villagery CityPerson. Según el tipo pasado al PersonFactoryobjeto, devolvemos el objeto concreto original como interfaz IPerson.

Un método de fábrica es sólo una adición a PersonFactoryla clase. Crea el objeto de la clase a través de interfaces pero, por otro lado, también permite que la subclase decida qué clase se instancia.

interfaz pública IProducto { cadena GetName (); bool SetPrice ( precio doble ); }       Teléfono de clase pública : IProduct { privado double_price ;        cadena pública GetName () { return "Apple TouchPad" ; }       public bool SetPrice ( precio doble ) { _price = precio ; devolver verdadero ; } }          /* Casi igual que Factory, solo una exposición adicional para hacer algo con el método creado */ public abstract class ProductAbstractFactory { protected abstract IProduct MakeProduct ();        public IProduct GetObject () // Implementación del método de fábrica. { devuelve esto . HacerProducto (); } }       clase pública PhoneConcreteFactory : ProductAbstractFactory { anulación protegida IProduct MakeProduct () { IProduct producto = nuevo teléfono (); // Haz algo con el objeto después de obtenerlo. producto . EstablecerPrecio ( 20.30 ); producto devuelto ; } }                   

Puedes ver que lo hemos usado MakeProducten concreteFactory. Como resultado, puedes llamar fácilmente MakeProduct()desde allí para obtener el archivo IProduct. También puede escribir su lógica personalizada después de obtener el objeto en el método de fábrica concreto. GetObject se vuelve abstracto en la interfaz Factory.

Java

Este ejemplo de Java es similar a uno del libro Design Patterns .

MazeGame utiliza Salas pero asigna la responsabilidad de crear Salas a sus subclases que crean las clases concretas. El modo de juego normal podría utilizar este método de plantilla:

clase abstracta pública Habitación { conexión vacía abstracta ( Habitación habitación ); }        public class MagicRoom extiende Room { public void connect ( Room room ) {} }          public class OrdinaryRoom extiende Room { public void connect ( Room room ) {} }          clase abstracta pública MazeGame { Lista final privada < Habitación > habitaciones = nueva ArrayList <> ();            public MazeGame () { Habitación habitación1 = hacerHabitación (); Habitación habitación2 = hacerHabitación ( ); habitación 1 . conectar ( habitación2 ); habitaciones . agregar ( habitación1 ); habitaciones . agregar ( habitación2 ); }               habitación protegida abstracta makeRoom (); }   

En el fragmento anterior, el MazeGameconstructor es un método de plantilla que genera una lógica común. Se refiere al makeRoommétodo de fábrica que encapsula la creación de salas de modo que se puedan usar otras salas en una subclase. Para implementar el otro modo de juego que tiene salas mágicas, basta con anular el makeRoommétodo:

clase pública MagicMazeGame extiende MazeGame { @Override protected MagicRoom makeRoom () { return new MagicRoom (); } }              clase pública OrdinaryMazeGame extiende MazeGame { @Override protected OrdinaryRoom makeRoom () { return new OrdinaryRoom (); } }              MazeGame ordinarioGame = nuevo OrdinaryMazeGame (); MazeGame magicGame = nuevo MagicMazeGame ();        

PHP

A continuación se muestra otro ejemplo en PHP , esta vez utilizando implementaciones de interfaz en lugar de subclases (sin embargo, se puede lograr lo mismo mediante subclases). Es importante tener en cuenta que el método de fábrica también puede definirse como público y llamarse directamente mediante el código del cliente (a diferencia del ejemplo de Java anterior).

/* Interfaces de fábrica y automóvil */interfaz  CarFactory {  función pública  makeCar () : Coche ; }  interfaz  Coche {  función pública  getType () : cadena ; }  /* Implementaciones concretas de la fábrica y el automóvil */clase  SedanFactory  implementa  CarFactory {  función pública  makeCar () : Coche { return new Sedan (); } }       clase  Sedan  implementa  Coche {  función pública  getType () : cadena { retorno 'Sedan' ; } }      /* Cliente */$fábrica  =  nueva  SedanFactory (); $coche  =  $fábrica -> makeCar (); imprimir  $coche -> getType ();

Pitón

Igual que el ejemplo de Java.

de  abc  importar  ABC ,  método abstractoclase  MazeGame ( ABC ):  def  __init__ ( self )  ->  Ninguno :  self . habitaciones  =  []  self . _preparar_habitaciones () def  _prepare_rooms ( self )  ->  Ninguno :  habitación1  =  self . make_room ()  habitación2  =  self . hacer espacio () habitación 1 . conectar ( habitación2 )  uno mismo . habitaciones . anexar ( habitación1 )  self . habitaciones . agregar ( habitación2 ) def  play ( self )  ->  Ninguno : print  ( f " Jugando usando { self.rooms [ 0 ] } " ) @abstractmethod  def  make_room ( self ):  rise  NotImplementedError ( "¡Deberías implementar esto!" )clase  MagicMazeGame ( MazeGame ):  def  make_room ( self )  ->  "MagicRoom" :  devuelve  MagicRoom ()clase  OrdinaryMazeGame ( MazeGame ):  def  make_room ( self )  ->  "OrdinaryRoom" :  devuelve  OrdinaryRoom ()clase  Sala ( ABC ):  def  __init__ ( self )  ->  Ninguno :  self . habitaciones_conectadas  =  [] def  conectar ( self ,  habitación :  "Habitación" )  ->  Ninguno :  self . habitaciones_conectadas . añadir ( habitación )clase  MagicRoom ( Habitación ):  def  __str__ ( self )  ->  str :  return  "Habitación mágica"clase  OrdinaryRoom ( Habitación ):  def  __str__ ( self )  ->  str :  return  "Habitación ordinaria"JuegoOrdinario  =  JuegoLaberintoOrdinario () JuegoOrdinario . jugar ()magicGame  =  MagicMazeGame () magicGame . jugar ()

Usos

Ver también

Referencias

  1. ^ Erich Gamma; Richard Helm; Ralph Johnson; John Vlissides (1994). Patrones de diseño: elementos de software reutilizable orientado a objetos . Addison Wesley. págs. 121 y siguientes. ISBN 0-201-63361-2.
  2. ^ Hombre libre, Eric; Hombre libre, Elisabeth; Kathy, Sierra; Bert, Bates (2004). Hendrickson, Mike; Loukides, Mike (eds.). Patrones de diseño Head First (libro de bolsillo) . vol. 1. O'REILLY. pag. 162.ISBN 978-0-596-00712-6. Consultado el 12 de septiembre de 2012 .
  3. ^ "El patrón de diseño del método Factory: estructura y colaboración". w3sDesign.com . Consultado el 12 de agosto de 2017 .
  4. ^ Erich Gamma (1994). Patrones de diseño: elementos de software reutilizable orientado a objetos . Addison Wesley. págs. 123 y siguientes. ISBN 0-201-63361-2.

enlaces externos