Método de fábrica (patrón de diseño)

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 11 de septiembre de 2018; las comprobaciones requieren 32 ediciones .
método de fábrica
Método de fábrica

Método de fábrica
Tipo de generando
Objetivo Para crear objetos de diferentes tipos con una interfaz
ventajas Creación de objetos, independientemente de sus tipos y la complejidad del proceso de creación.
menos Incluso para un solo objeto, debe crear una fábrica adecuada, lo que aumenta el código.
Descrito en Patrones de diseño

Un método de fábrica ( ing.  Factory Method ) o un constructor virtual ( ing.  Virtual Constructor ) es un patrón de diseño de generación que proporciona subclases (clases secundarias, subclases) con una interfaz para crear instancias de una determinada clase. En el momento de la creación, los descendientes pueden determinar qué clase crear. En otras palabras, esta plantilla delega la creación de objetos a los descendientes de la clase principal. Esto le permite usar clases no concretas en el código del programa, sino manipular objetos abstractos en un nivel superior.

Propósito

Define una interfaz para crear un objeto, pero deja que las subclases decidan en qué clase basar el objeto. Un método de fábrica permite que una clase delegue la creación de subclases. Se usa cuando:

Estructura

Ventajas

Desventajas

Ejemplos de código

Rápido

Ejemplo rápido protocolo Producto {     func getName () -> String } class ProductoConcretoA : Producto {     func getName () -> String {  return "ProductoConcretoA" } } class ProductoConcretoB : Producto {     func getName () -> String { return "ProductoConcretoB" } } Creador del protocolo {     func factoryMethod () -> Producto } clase ConcreteCreatorA : Creador {     func factoryMethod () -> Producto { return ConcreteProductA () } } clase ConcreteCreatorB : Creador {     func factoryMethod () -> Producto { return ConcreteProductB () } } let creadorA = CreadorConcretoA () let creadorB = CreadorConcretoB () Let creadores : [ Creador ] = [ CreadorA , CreadorB ] creadores _ forEach {     let producto = $ 0. factoryMethod ()     print ( producto . getName ()) }

Pitón

Ejemplo en Python # codificación: utf-8 """Tipos de afinación""" class Cultura : """Cultura""" def __repr__ ( self ): return self . __str__ () class Democracia ( Cultura ): def __str__ ( self ): return 'Democracia' class Dictadura ( Cultura ): def __str__ ( self ): return 'Dictadura' clase Gobierno : """El gobierno mismo""" cultura = '' def __str__ ( self ): return self . cultura _ __str__ () def __repr__ ( auto ): devuelve auto . cultura _ __repr__ () def set_culture ( self ): """Establecer compilación para el gobierno: este es nuestro método de fábrica""" aumentar AttributeError ( 'Cultura no implementada' ) clase GobiernoA ( Gobierno ): def set_cultura ( auto ): auto . cultura = democracia () clase GobiernoB ( Gobierno ): def set_cultura ( self ): self . cultura = dictadura () g1 = GobiernoA () g1 . set_cultura () imprimir ( str ( g1 )) g2 = GobiernoB () g2 . set_cultura () imprimir ( str ( g2 ))

Java

ejemplo java interfaz Producto { } clase ProductoConcretoA implementa Producto { } clase ProductoConcretoB implementa Producto { } creador de clase abstracta { public abstract Product factoryMethod (); } clase ConcreteCreatorA extiende Creador { @Override public Product factoryMethod () { return new ConcreteProductA (); } } clase ConcreteCreatorB extiende Creador { @Override public Product factoryMethod () { return new ConcreteProductB (); } } public class FactoryMethodExample { public static void main ( String [] args ) { // una matriz de creadores Creator [] creadores = { new ConcreteCreatorA (), new ConcreteCreatorB ()}; // iterar sobre creadores y crear productos para ( Creador creador : creadores ) { Producto producto = creador . método de fábrica (); sistema _ fuera _ printf ( "Creado {%s}\n" , producto .getClass ( )); } } }

Resultado del trabajo:

Creó {clase ConcreteProductA} Creó {clase ConcreteProductB}

C++

Ejemplo en C++ #incluir <iostream> #incluir <cadena> utilizando el espacio de nombres estándar ; producto de estructura { cadena virtual getName () = 0 ; ~ Producto virtual (){} }; struct ConcreteProductA : Producto { cadena getNombre (){ devuelve "ProductoConcretoA" ;} }; struct ProductoConcretoB : Producto { cadena getName (){ devuelve "ProductoConcretoB" ;} }; Creador de la estructura { Producto virtual * factoryMethod () = 0 ; }; struct ConcreteCreatorA : Creador { Producto * factoryMethod (){ return new ConcreteProductA ();} }; struct ConcreteCreatorB : Creador { Producto * factoryMethod (){ return new ConcreteProductB ();} }; int principal () { CreadorConcretoA CreadorA ; CreadorConcretoB CreadorB ; // Una matriz de creadores Creator * Creators [] = { & CreatorA , & CreatorB }; // Iterar sobre los creadores y crear productos para ( auto && creador : creadores ){ Producto * producto = creador -> factoryMethod (); cout << producto -> getNombre () << endl ; eliminar producto ; } devolver 0 ; }

Resultado del trabajo:
ConcreteProductA
ConcreteProductB

C#

Ejemplo en C# utilizando el sistema ; usando System.Collections.Generic ; espacio de nombres Factory { public abstract class Product { public abstract string GetType (); } public class ProductoConcretoA : Producto { public override string GetType () { return " ProductoConcretoA " ; } } public class ProductoConcretoB : Producto { public override string GetType () { return " ProductoConcretoB " ; } } Creador de clase abstracta pública { Product FactoryMethod abstracto público (); } public class ConcreteCreatorA : Creator { public override Product FactoryMethod () { return new ConcreteProductA (); } } clase pública ConcreteCreatorB : Creador { public override Product FactoryMethod () { return new ConcreteProductB (); } } public static class MainApp { public static void Main () { // una matriz de creadores Creator [] creadores = { new ConcreteCreatorA (), new ConcreteCreatorB () }; // iterar sobre creadores y crear productos para cada uno ( Creador creador en creadores ) { Producto producto = creador . método de fábrica (); consola _ WriteLine ( "Creado {0}" , producto .GetType ( )); } // Esperar a la Consola del usuario . leer (); } } }

JavaScript

Ejemplo de JavaScript ES5 var NewConcreteCreatorA = ()=>{ return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductA" };}} }; var NewConcreteCreatorB = ()=>{ return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductB" };}} }; var creadores = [ NewConcreteCreatorA (), NewConcreteCreatorB ()]; creadores _ map ( creador => consola . log ( creador . factoryMethod (). getName ())); Ejemplo de JavaScript ES6 clase Producto { GetName () {} } class ProductoConcretoA extiende el Producto { GetName () { return ' ProductA ' } } class ProductoConcretoB extiende el Producto { GetName () { return ' ProductB ' } } creador de clases { FactoryMethod () {} } clase ConcreteCreatorA extiende Creador { FactoryMethod () { return new ConcreteProductA () } } clase ConcreteCreatorB extiende Creador { FactoryMethod () { return new ConcreteProductB () } } // Una matriz de creadores const creadores = [ new ConcreteCreatorA (), new ConcreteCreatorB () ] const productos = [] // Iterar sobre creadores y crear productos para ( permitir creadores de creadores ) { productos . empujar ( creador.FactoryMethod ( ). getName ( )) } consola _ registro ( productos ) Ejemplo en TypeScript interfaz Producto { GetName () : cadena } class ProductoConcretoA implementa Producto { public GetName () { return ' ProductA ' } } clase ConcreteProductB implementa Producto { public GetName () { return 'ProductB' } } Creador de interfaz { FactoryMethod () : Producto } clase ConcreteCreatorA implementa Creator { public FactoryMethod () { return new ConcreteProductA () } } clase ConcreteCreatorB implementa Creator { public FactoryMethod () { return new ConcreteProductB () } } // Una matriz de creadores const creadores : Creador [] = [ new ConcreteCreatorA (), new ConcreteCreatorB () ] const productos : string [] = [] // Iterar sobre creadores y crear productos para ( permitir creadores de creadores ) { productos . empujar ( creador.FactoryMethod ( ). getName ( )) } consola _ registro ( productos )

PHP5

ejemplo PHP <?php interfaz Producto { public function GetName (); } class ProductoConcretoA implementa Producto { public function ObtenerNombre () { return "ProductoA " ; } } clase ConcreteProductB implementa Product { public function GetName () { return "ProductB" ; } } interfaz Creador { función pública FactoryMethod (); } clase ConcreteCreatorA implementa Creator { public function FactoryMethod () { return new ConcreteProductA (); } } clase ConcreteCreatorB implementa Creator { public function FactoryMethod () { return new ConcreteProductB (); } } // Una matriz de creadores $creators = array ( new ConcreteCreatorA (), new ConcreteCreatorB () ); // Iterar sobre los creadores y crear productos para cada uno ( $creators as $ creator ) { $products [] = $creator -> FactoryMethod () -> getName (); } encabezado ( "tipo de contenido: texto/sin formato" ); echo var_export ( $productos ); ?>

PHP5 versión moderna

Versión abreviada del patrón más utilizado en PHP <?php /** * Class Animal, más de 20 años desde la primera edición del libro y este patrón ha evolucionado un poco, * y ahora siempre usa su forma abreviada */ abstract class Animal { // método de fábrica que devuelve un objeto basado en el tipo public static function initial ( $animal ) { return new $animal (); } voz de función pública abstracta (); } class Lion extends Animal { public function voice () { echo 'Rrrrrrr soy el león <br />' . PHP_EOL ; } } class Cat extends Animal { public function voice () { echo 'Miau, miau soy el gatito <br />' . PHP_EOL ; } } $animal1 = Animal :: inicial ( 'León' ); $animal2 = Animal :: inicial ( 'Gato' ); $animal1 -> voz (); $animal2 -> voz ();

Delfos

ejemplo de Delfos programa FactoryMethod ; {$CONSOLA DE TIPO DE APLICACIÓN} utiliza SysUtils ; escribe // Producto TProducto = clase ( TObject ) public function GetName : string ; virtuales ; abstracto ; fin ; // ProductoConcretoA TProductoConcretoA = class ( TProducto ) public function GetName : string ; anular ; fin ; // ProductoConcretoB TProductoConcretoB = class ( TProducto ) public function GetName : string ; anular ; fin ; // Creador TCreator = clase ( TObject ) public function FactoryMethod : TProduct ; virtuales ; abstracto ; fin ; // ConcreteCreatorA TConcreteCreatorA = class ( TCreator ) public function FactoryMethod : TProduct ; anular ; fin ; // ConcreteCreatorB TConcreteCreatorB = class ( TCreator ) public function FactoryMethod : TProduct ; anular ; fin ; { ProductoConcretoA } función TProductoConcretoA . ObtenerNombre : cadena ; comenzar Resultado := 'ProductoConcretoA' ; fin ; {ProductoConcretoB} función TProductoConcretoB . ObtenerNombre : cadena ; comenzar Resultado := 'ConcreteProductB' ; fin ; { ConcreteCreatorA } función TConcreteCreatorA . FactoryMethod : TProducto ; comenzar Resultado := TConcreteProductA . crear ; fin ; { CreadorConcretoB } función TCreadorConcretoB . FactoryMethod : TProducto ; comenzar Resultado := TConcreteProductB . crear ; fin ; const Cuenta = 2 ; var Creadores : matriz [ 1 .. Cuenta ] de TCreator ; Producto : TProducto ; yo : entero ; begin // Una matriz de creadores Creators [ 1 ] := TConcreteCreatorA . crear ; Creadores [ 2 ] := TConcreteCreatorB . crear ; // Iterar sobre creadores y crear productos para I := 1 to Count do begin Product := Creators [ I ] . método de fábrica ; WriteLn ( Producto . GetName ) ; producto _ Gratis ; fin ; para I := 1 para Contar do Creadores [ I ] . Gratis ; Leerln ; fin _ Ejemplo de Delphi (constructores virtuales) programa FactoryMethod ; {$CONSOLA DE TIPO DE APLICACIÓN} utiliza SysUtils ; escribe // Producto TProducto = clase ( TObject ) private SubName : string ; función pública GetName : cadena ; virtuales ; abstracto ; función GetFullName : cadena ; constructor Crear ; virtuales ; abstracto ; fin ; TProductClass = clase de TProduct ; // ProductoConcretoA TProductoConcretoA = class ( TProducto ) public function GetName : string ; anular ; constructor Crear ; anular ; fin ; // ProductoConcretoB TProductoConcretoB = class ( TProducto ) public function GetName : string ; anular ; constructor Crear ; anular ; fin ; { TProducto} función TProducto . GetFullName : cadena ; comenzar Resultado := ObtenerNombre + ' : ' + SubNombre ; fin ; { ProductoConcretoA } constructor TProductoConcretoA . crear ; comenzar heredado ; SubNombre := 'Producto A subnombre' ; fin ; función TProductoConcretoA . ObtenerNombre : cadena ; comenzar Resultado := 'ProductoConcretoA' ; fin ; {ProductoConcretoB} constructor TProductoConcretoB . crear ; comenzar heredado ; SubNombre := 'Producto B subnombre' ; fin ; función TProductoConcretoB . ObtenerNombre : cadena ; comenzar Resultado := 'ConcreteProductB' ; fin ; const Cuenta = 2 ; var Creadores : array [ 1 .. Count ] de TProductClass ; Producto : TProducto ; yo : entero ; begin // Una matriz de creadores Creators [ 1 ] := TConcreteProductA ; Creadores [ 2 ] := TConcreteProductB ; // Iterar sobre creadores y crear productos para I := 1 to Count do begin Product := Creators [ I ] . crear ; WriteLn ( Producto . GetFullName ) ; producto _ Gratis ; fin ; Leerln ; fin _

Script de acción 3.0

Ejemplo en ActionScript 3.0 creador de clase protegida { función protegida factoryMethod () : Producto { return null ; } función pública someFunction () : void { var _product : Product = factoryMethod (); _producto . hacerAlgo (); } } clase pública ConcreteCreatorA extiende Creador { anula la función protegida factoryMethod () : Product { return new ConcreteProductA (); } } clase pública ConcreteCreatorB extiende Creador { anula la función protegida factoryMethod () : Product { return new ConcreteProductB (); } } interfaz pública Producto { función doSome () : void {} } clase interna ProductoConcretoA implementa Producto { función pública hacerAlgunos () : void {} } clase interna ProductoConcretoB implementa Producto { función pública hacerAlgunos () : void {} } // IMPLEMENTACIÓN public class Main { public function Main () { var _creatorA : ConcreteCreatorA = new ConcreteCreatorA (); _creadorA . algunaFunción (); var _creatorB : ConcreteCreatorB = new ConcreteCreatorB (); _creadorB . algunaFunción (); } }

escala

ejemplo de escala clase abstracta _ _ def getNombre : Cadena } clase abstracta _ _ def getProducto : ProductoAbstracto } clase Beer extiende AbstractProduct { anular def getName : String = "Cerveza" } clase Wine extiende AbstractProduct { anular def getName : String = "Vino" } clase BeerCreator extiende AbstractCreator { anular def getProduct : AbstractProduct = nueva cerveza } clase WineCreator extiende AbstractCreator { anular def getProduct : AbstractProduct = new Wine } prueba de objeto { private def printProductName ( creator : AbstractCreator ) : Unidad = println ( creator . getProduct . getName ) def main ( args : Array [ String ]) : Unit = printProductName ( new BeerCreator ) printProductName ( new WineCreator ) }

Resultado del trabajo:
Creado: Vino Creado: Cerveza

Rubí

Ejemplo en rubí módulo FactoryMethod # Clase de producto Product attr_reader : productType def initialize @productType = nil end end # ProductoConcretoA class ProductoConcretoA < Product attr_reader : productType def initialize @productType = " ConcreteProductA " end end # ProductoB Concreto class ProductoB Concreto < Product attr_reader : tipoProducto def initialize @productType = "ProductoConcretoB" end end # Creador clase Creador def factoryMethod Producto . nuevo final final # ConcreteCreatorA class ConcreteCreatorA < Creator def factoryMethod ConcreteProductA . nuevo final final # ConcreteCreatorB class ConcreteCreatorB < Creator def factoryMethod ConcreteProductB . nuevo final final final # Módulo de cliente Cliente incluye FactoryMethod creadores = [ ConcreteCreatorA . nuevo , ConcreteCreatorB . nuevo ] creadores _ cada uno hace | creador | pone " #{ creador . clase } crear producto: \t #{ creador . métodofábrica . tipoproducto } " final # => FactoryMethod::ConcreteCreatorA crear Producto: ConcreteProductA # => FactoryMethod::ConcreteCreatorB crear Producto: ConcreteProductB end

Literatura

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Técnicas de diseño orientado a objetos. Patrones de diseño = Patrones de diseño : Elementos de software orientado a objetos reutilizable. - San Petersburgo. : "Pedro" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (también ISBN 5-272-00355-1 )