Fábrica abstracta (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 2 de marzo de 2018; las comprobaciones requieren 25 ediciones .
Fábrica abstracta
fábrica abstracta
Tipo de generando
Objetivo Proporciona una interfaz para crear familias de objetos relacionados o interdependientes sin especificar sus clases concretas.
Estructura
Se aplica en casos
  • Cuando el programa debe ser independiente del proceso y tipos de nuevos objetos creados.
  • Cuando sea necesario crear familias o grupos de objetos interrelacionados, excluyendo la posibilidad de uso simultáneo de objetos de estos diferentes conjuntos en un mismo contexto [1] .
ventajas
  • aísla clases específicas;
  • simplifica la sustitución de familias de productos;
  • garantiza la compatibilidad del producto.
menos
  • es difícil agregar soporte para un nuevo tipo de producto.
Descrito en Patrones de diseño

Una  fábrica abstracta es un patrón de diseño generativo que proporciona una interfaz para crear familias de objetos interrelacionados o interdependientes sin especificar sus clases concretas. El patrón se implementa creando una clase abstracta Factory, que es una interfaz para crear componentes del sistema (por ejemplo, para una interfaz de ventana, puede crear ventanas y botones). Luego se escriben clases que implementan esta interfaz [2] .

Cita

Proporciona una interfaz para crear familias de objetos relacionados o interdependientes sin especificar sus clases concretas.

Implementación

Ventajas

Contras

Aplicación

Ejemplos

Ejemplo de Swift

Código fuente rápido //: Playground - sustantivo: un lugar donde la gente puede jugar /// <summary> /// Clase de fábrica abstracta /// </summary> protocol AbstractFactory { func createProductA () -> AbstractProductA func createProductB () -> AbstractProductB } /// <summary> /// Factory class #1 /// </summary> class ConcreteFactory1 : AbstractFactory { public func createProductA () -> AbstractProductA { return ProductA1 () } public func createProductB () -> AbstractProductB { return ProductB1 () } } /// <summary> /// Factory class #2 /// </summary> class ConcreteFactory2 : AbstractFactory { public func createProductA () -> AbstractProductA { return ProductA2 () } public func createProductB () -> AbstractProductB { return ProductB2 () } } /// <summary> /// Producto abstracto clase A /// </summary> protocol AbstractProductA {} // /// <summary> /// Producto abstracto clase B /// </summary> protocol AbstractProductB { func interactuar ( a : AbstractProductA ) } /// <summary> /// Primera clase de producto de tipo A /// </summary> class ProductA1 : AbstractProductA {} /// <summary> /// Primera clase de producto de tipo B /// </summary> class ProductB1 : AbstractProductB { public func interact ( a : AbstractProductA ) { print ( " \( type ( of : self )) interactúa con \ ( tipo ( de : a . self )) " ) } } /// <summary> /// Segunda clase de producto de tipo A /// </summary> class ProductA2 : AbstractProductA {} /// <summary> /// Segunda clase de producto de tipo B /// </summary> class ProductB2 : AbstractProductB { public func interact ( a : AbstractProductA ) { print ( " \( type ( of : self )) interactúa con \ ( tipo ( de : a . self )) " ) } } /// <summary> /// La clase de cliente en la que tiene lugar la interacción entre objetos /// </summary> class Client { private let _abstractProductA : AbstractProductA private let _abstractProductB : AbstractProductB // Constructor public init ( factory : AbstractFactory ) { _abstractProductB = factory . crearProductoB (); _abstractProductA = fábrica . crearProductoA (); } ejecución de función pública () { _abstractProductB . interactuar ( a : _abstractProductA ) } } /// <summary> /// Punto de entrada de la aplicación /// </summary> // Llamando a la fábrica abstracta #1 let factory1 = ConcreteFactory1 () let client1 = Client ( factory : factory1 ) client1 . correr () // Llamar a la fábrica abstracta #2 let factory2 = ConcreteFactory2 () let client2 = Client ( factory : factory2 ) client2 . correr ()

Ejemplo en C# [3]

Código fuente en C Sharp utilizando el sistema ; namespace DoFactory.GangOfFour.Abstract.Structural { class MainApp { /// <summary> /// Punto de entrada de la aplicación /// </summary> public static void Main () { // Abstract factory call #1 AbstractFactory factory1 = new ConcreteFactory1 (); Cliente cliente1 = nuevo Cliente ( fábrica1 ); cliente1 . ejecutar (); // Llamar a la fábrica abstracta #2 AbstractFactory factory2 = new ConcreteFactory2 (); Cliente cliente2 = nuevo Cliente ( fábrica2 ); cliente2 . ejecutar (); // Esperando la consola de entrada . Clave de lectura (); } } /// <summary> /// clase de fábrica abstracta /// </summary> clase abstracta AbstractFactory { public abstract AbstractProductA CreateProductA (); Resumen público AbstractProductB CreateProductB (); } /// <summary> /// Factory class #1 /// </summary> class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA () { return new ProductA1 (); } public override AbstractProductB CreateProductB () { return nuevo ProductB1 (); } } /// <summary> /// Factory class #2 /// </summary> class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA () { return new ProductA2 (); } public override AbstractProductB CreateProductB () { return new ProductB2 (); } } /// <summary> /// clase de producto abstracto A /// </summary> clase abstracta AbstractProductA { } /// <summary> /// Clase de producto abstracto B /// </summary> clase abstracta ProductoAbstractoB { public abstract void Interact ( ProductoAbstractoA a ); } /// <summary> /// Primera clase de producto de tipo A /// </summary> class ProductA1 : AbstractProductA { } /// <summary> /// Primera clase de producto de tipo B /// </summary> class ProductB1 : AbstractProductB { public override void Interact ( AbstractProductA a ) { Console . WriteLine ( this . GetType (). Name + " interactúa con " + a . GetType (). Name ); } } /// <summary> /// Segunda clase de producto de tipo A /// </summary> class ProductA2 : AbstractProductA { } /// <summary> /// Segunda clase de producto de tipo B /// </summary> class ProductB2 : AbstractProductB { public override void Interact ( AbstractProductA a ) { Console . WriteLine ( this . GetType (). Name + " interactúa con " + a . GetType (). Name ); } } /// <summary> /// La clase de cliente en la que tiene lugar la interacción entre objetos /// </summary> class Client { private AbstractProductA _abstractProductA ; privado ProductoAbstractoB _ProductoAbstractoB ; // Constructor public Client ( AbstractFactory factory ) { _abstractProductB = factory . CrearProductoB (); _abstractProductA = fábrica . CrearProductoA (); } public void Ejecutar () { _abstractProductB . Interactuar ( _abstractProductA ); } } }

Ejemplo de Java

Fuente Java clase pública AbstractFactoryExample { public static void main ( String [] args ) { AbstractFactory factory1 = new ConcreteFactory1 (); Cliente cliente1 = nuevo Cliente ( fábrica1 ); cliente1 . ejecutar (); AbstractFactory factory2 = new ConcreteFactory2 (); Cliente cliente2 = nuevo Cliente ( fábrica2 ); cliente2 . ejecutar (); } } class Client { private AbstractProductA productA ; privado AbstractProductB productoB ; Cliente ( Fábrica AbstractFactory ) { productA = fábrica . crearProductoA (); productoB = fábrica . crearProductoB (); } void ejecutar () { productoB . interactuar ( productoA ); } } interfaz AbstractFactory { AbstractProductA createProductA (); AbstractProductB createProductB (); } interfaz AbstractProductA { void interactuar ( AbstractProductB b ); } interface AbstractProductB { void interact ( AbstractProductA a ); } clase ConcreteFactory1 implementa AbstractFactory { @Override public AbstractProductA createProductA () { return new ProductA1 (); } @Override public AbstractProductB createProductB () { return new ProductB1 (); } } clase ConcreteFactory2 implementa AbstractFactory { @Override public AbstractProductA createProductA () { return new ProductA2 (); } @Override public AbstractProductB createProductB () { return new ProductB2 (); } } class ProductA1 implementa AbstractProductA { @Override public void interact ( AbstractProductB b ) { System . fuera _ println ( this . getClass (). getName () + " interactúa con " + b . getClass (). getName ()); } } class ProductB1 implementa AbstractProductB { @Override public void interact ( AbstractProductA a ) { System . fuera _ println ( this . getClass (). getName () + " interactúa con " + a . getClass (). getName ()); } } class ProductA2 implementa AbstractProductA { @Override public void interact ( AbstractProductB b ) { System . fuera _ println ( this . getClass (). getName () + " interactúa con " + b . getClass (). getName ()); } } class ProductB2 implementa AbstractProductB { @Override public void interact ( AbstractProductA a ) { System . fuera _ println ( this . getClass (). getName () + " interactúa con " + a . getClass (). getName ()); } }

Ejemplo de PHP5

código fuente PHP5 interfaz IHead { función pública drawHead ( $x , $y ); } class RedHead implementa IHead { public function drawHead ( $x , $y ) { echo 'Tu cabeza roja en el eje x =' . $ x . ' y el eje y = ' . $ y . '</br>' . PHP_EOL ; } } class WhiteHead implementa IHead { public function drawHead ( $x , $y ) { echo 'Tu cabeza blanca en el eje x =' . $ x . ' y el eje y = ' . $ y . '</br>' . PHP_EOL ; } } interfaz IBody { función pública dibujarCuerpo ( $x , $y ); } class RedBody implementa IBody { public function drawBody ( $x , $y ) { echo 'Tu cuerpo rojo en el eje x =' . $ x . ' y el eje y = ' . $ y . '</br>' . PHP_EOL ; } } class WhiteBody implementa IBody { public function drawBody ( $x , $y ) { echo 'Tu cuerpo blanco en el eje x =' . $ x . ' y el eje y = ' . $ y . '</br>' . PHP_EOL ; } } /** * Interfaz ISnowman: esta es una fábrica abstracta */ interfaz ISnowman { public function drawHead ( $x , $y ); función pública dibujarCuerpo ( $x , $y ); } /** * Class WhiteSnowman - fábrica de hormigón */ class WhiteSnowman implements ISnowman { protected $head ; $cuerpo protegido ; public function __construct () { $this -> head = new WhiteHead (); $este -> cuerpo = new WhiteBody (); } función pública drawHead ( $x , $y ) { $this -> head -> drawHead ( $x , $y ); } public function dibujarCuerpo ( $x , $y ) { $este -> cuerpo -> dibujarCuerpo ( $x , $y ); } } /** * Class RedSnowman - fábrica de hormigón */ class RedSnowman implements ISnowman { protected $head ; $cuerpo protegido ; public function __construct () { $this -> head = new RedHead (); $este -> cuerpo = new RedBody (); } función pública drawHead ( $x , $y ) { $this -> head -> drawHead ( $x , $y ); } public function dibujarCuerpo ( $x , $y ) { $este -> cuerpo -> dibujarCuerpo ( $x , $y ); } } function muñeco de nieve ( ISnowman $snowman ) { $snowman -> drawHead ( 1 , 1 ); $muñeco de nieve -> dibujarCuerpo ( 1 , 2 ); } $tipoMuñeco de nieve = 'rojo' ; // seleccionamos el tipo de familia al principio del código if ( $typeSnowman == 'red' ) $snowman = new RedSnowman (); else $muñeco de nieve = new MuñecodenieveBlanco (); muñeco de nieve ( $ muñeco de nieve );

Ejemplo de Python

Código fuente en Python de abc import ABCMeta , método abstracto clase Cerveza ( metaclase = ABCMeta ): pasar clase Merienda ( metaclase = ABCMeta ): @abstractmethod def interact ( self , beer : Beer ) -> Ninguno : pasar clase AbstractShop ( metaclase = ABCMeta ): @abstractmethod def buy_beer ( self ) -> Beer : pass @abstractmethod def buy_snack ( self ) -> Snack : pase clase Tuborg ( Cerveza ): pase clase Staropramen ( Cerveza ): pase Clase Cacahuetes ( Merienda ): def interact ( self , cerveza : Cerveza ) -> Ninguno : imprimir ( 'Bebimos una botella de cerveza {} y la comimos con maní' . format ( cerveza . __clase__ . __nombre__ )) Chips de clase ( Merienda ): def interact ( self , cerveza : Cerveza ) -> Ninguno : imprimir ( 'Bebimos unas cuantas cervezas {} y comimos una bolsa de papitas' . format ( cerveza . __clase__ . __nombre__ )) clase TiendaCara ( AbstractShop ): def comprar_cerveza ( self ) -> Cerveza : volver Tuborg () def buy_snack ( self ) -> Snack : return Peanuts () clase CheapShop ( AbstractShop ): def comprar_cerveza ( self ) -> Cerveza : volver Staropramen () def buy_snack ( self ) -> Snack : return Chips () if __name__ == '__principal__' : tienda_caro = Tienda Caro () tienda_barato = Tienda Barato () print ( 'SALIDA:' ) cerveza = tienda_caro . comprar_cerveza () bocadillo = tienda_barata . comprar_merienda () merienda . interactuar ( cerveza ) cerveza = tienda_barata . comprar_cerveza () merienda = tienda_caro . comprar_merienda () merienda . interactuar ( cerveza ) ''' SALIDA: Nos bebimos unas latas de cerveza Tuborg y nos comimos una bolsa de patatas fritas Nos bebimos una botella de cerveza Staropramen y la mordimos con cacahuetes '''

Ejemplo de Scala

Código fuente de Scala clase abstracta AbstractTerrestrialAnimal { def caminar : Cadena } clase abstracta _ _ def nadar : Cadena _ clase abstracta _ _ def getCity : Cadena def getTerrestrialAnimal : AbstractTerrestrialAnimal def getWaterAnimal : AbstractWaterAnimal } clase Wolverine extiende AbstractTerrestrialAnimal { anular def caminar : String = "Wolverine está caminando" } clase HoneyBadger extiende AbstractTerrestrialAnimal { anular def caminar : String = "El tejón de miel está caminando" } clase Walrus extiende AbstractWaterAnimal { anular def nadar : String = "La morsa está nadando" } clase SeaLion extiende AbstractWaterAnimal { anular def nadar : String = "El león marino está nadando" } class MunichZoo extiende AbstractZoo { anular def getCity : String = "Munich" anular def getTerrestrialAnimal : AbstractTerrestrialAnimal = new Wolverine anular def getWaterAnimal : AbstractWaterAnimal = new Walrus } class CapeTownZoo extiende AbstractZoo { anular def getCity : String = "Ciudad del Cabo" anular def getTerrestrialAnimal : AbstractTerrestrialAnimal = new HoneyBadger anular def getWaterAnimal : AbstractWaterAnimal = new SeaLion } objeto PruebaFábricaAbstracta { private def testZoo ( zoo : AbstractZoo ): Unidad = { println ( s"Zoo of ${ zoo . getCity } :" ) println ( zoo . getTerrestrialAnimal . walk ) println ( zoo . getWaterAnimal . swim ) } def main ( args : Array [ String ]) Unidad = { testZoo ( nuevo CapeTownZoo ) testZoo ( nuevo MunichZoo ) } }

Ir ejemplo

Código fuente en Go paquete principal importar "fmt" tipo Unidad interfaz { Qué () cadena } tipo Interfaz de acción { Qué () cadena } tipo Lugar interfaz { Qué () cadena } type TransportFactory interfaz { MakeUnit () Unidad MakeAction () Acción MakePlace () Lugar } tipo de estructura de coche {} func ( self Car ) What () string { return "car" } tipo Estructura de viaje {} func ( self Ride ) What () string { return "ride" } tipo de estructura de carretera {} func ( self Road ) What () string { return "road" } tipo LandTransportFactory estructura {} func ( self LandTransportFactory ) MakeUnit () Unit { return & Car {} } func ( self LandTransportFactory ) MakeAction () Acción { return & Ride {} } func ( self LandTransportFactory ) MakePlace () Place { return & Road {} } tipo Barco estructura {} func ( self Barco ) Qué () cadena { return "barco" } escriba Estructura de vela {} func ( self Sail ) What () cadena { return "vela" } tipo Mar estructura {} func ( self Sea ) What () string { return "sea" } escriba la estructura SeaTransportFactory {} func ( self SeaTransportFactory ) MakeUnit () Unidad { return & Boat {} } func ( self SeaTransportFactory ) MakeAction () Acción { return & Sail {} } func ( self SeaTransportFactory ) MakePlace () Place { return & Sea {} } func action ( fábrica TransportFactory ) { unidad := fábrica . MakeUnit () unit_action := factory . MakeAction () lugar : = fábrica . Crear lugar () fmt . Printf ( "El %s %ss sobre el %s.\n" , unidad . Qué (), unit_action . Qué (), lugar . Qué ()) } función principal () { acción ( & LandTransportFactory {}) acción ( & SeaTransportFactory {}) }

Conclusión

El coche pasa por encima de la carretera. El barco navega sobre el mar.

Ejemplo de rubí

código fuente rubí module AbstractFactoryPattern # Proporcione una interfaz para crear familias de objetos relacionados o sin especificar sus clases concretas # Abstract Factory class WarriorFactory def create_knight raise NotImplementedError end def create_archer aumentar NotImplementedError end end # Concrete Factory class OrcWarriorFactory < WarriorFactory def create_knight OrcKnight . nuevo fin def create_archer OrcArcher . nuevo final final # Concrete Factory class ElfWarriorFactory < WarriorFactory def create_knight ElfKnight . nuevo fin def create_archer ElfArcher . nuevo final final # Clase de producto abstracto Caballero def inspeccionarse a sí mismo . clase _ nombre _ división ( '::' ) . último final final # Clase de producto abstracto Archer def inspeccionarse a sí mismo . clase _ nombre _ división ( '::' ) . último final final # Clase de producto OrcKnight < Knight end # Clase de producto ElfKnight < Knight end # Clase de producto OrcArcher < Archer final # Clase de producto ElfArcher < Archer end # Client class Army def initialize ( factory ) @knights = [] 3 . veces { @knights << fábrica . crear_caballero } @arqueros = [] 3 . veces { @archers << fábrica . crear_archer } fin def inspeccionar "Caballeros #{ @knights . map ( & :inspect ) } Archers #{ @archers . map ( & :inspect ) } " end end def auto . ejecutar orcos = Ejército . new ( OrcWarriorFactory . new ) pone "Ejército de orcos: #{ orcs . inspect } " duendes = ejército . new ( ElfWarriorFactory . new ) pone "Ejército de elfos: #{ elfos . inspeccionar } " end end AbstractFactoryPattern . correr # Ejército de orcos: Caballeros ["OrcKnight", "OrcKnight", "OrcKnight"] Arqueros ["OrcArcher", "OrcArcher", "OrcArcher"] # Ejército de elfos: Caballeros ["ElfKnight", "ElfKnight", "ElfKnight"] Arqueros ["ElfArcher", "ElfArcher", "ElfArcher"]

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 Reutilizable Orientado a Objetos. - San Petersburgo. : "Pedro" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (también ISBN 5-272-00355-1 )

Enlaces

Notas

  1. Patrón de fábrica abstracto . Consultado el 14 de junio de 2013. Archivado desde el original el 14 de junio de 2013.
  2. Generando patrones: Fábrica abstracta . Consultado el 14 de junio de 2013. Archivado desde el original el 14 de junio de 2013.
  3. Patrón de diseño .NET de Abstract Factory en C# y VB - dofactory.com . www.dofactory.com Fecha de acceso: 3 de marzo de 2016. Archivado desde el original el 3 de marzo de 2016.