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 |
Sí |
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:
- la clase no sabe de antemano qué objetos de qué subclases necesita crear.
- una clase está diseñada para que los objetos que crea estén especificados por subclases.
- la clase delega sus responsabilidades a una de varias subclases auxiliares, y se planea localizar el conocimiento de qué clase asume estas responsabilidades.
Estructura
- producto - producto
- define una interfaz para objetos creados por un método abstracto;
- ConcreteProduct - un producto específico
- implementa la interfaz del Producto ;
- creador _
- declara un método de fábrica que devuelve un objeto de tipo Producto . También puede contener una implementación "predeterminada" de este método;
- puede llamar a un método de fábrica para crear un objeto de tipo Producto ;
- ConcreteCreator - creador específico
- anula el método de fábrica para crear y devolver un objeto de la clase ConcreteProduct .
Ventajas
- le permite hacer que el código para crear objetos sea más universal, sin estar vinculado a clases específicas (ProductoConcreto), sino que opera solo con una interfaz común (Producto);
- le permite establecer una relación entre jerarquías de clases paralelas.
Desventajas
- la necesidad de crear un creador sucesor para cada nuevo tipo de producto (ConcreteProduct).
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 )