Metoda din fabrică (model de proiectare)

Versiunea actuală a paginii nu a fost încă revizuită de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită la 11 septembrie 2018; verificările necesită 32 de modificări .
metoda din fabrică
Metoda fabricii

Metoda fabricii
Tip de Generarea
Scop Pentru a crea obiecte de diferite tipuri cu o singură interfață
pro Crearea obiectelor, indiferent de tipurile lor și de complexitatea procesului de creație.
Minusuri Chiar și pentru un singur obiect, trebuie să creați o fabrică adecvată, care crește codul.
Descris în Design Patterns da

O metodă fabrică ( ing.  Factory Method ) sau un constructor virtual ( ing.  Virtual Constructor ) este un model de proiectare generator care oferă subclaselor (clase copii, subclase) cu o interfață pentru crearea instanțelor unei anumite clase. La momentul creării, descendenții pot determina ce clasă să creeze. Cu alte cuvinte, acest șablon deleagă crearea de obiecte descendenților clasei părinte. Acest lucru vă permite să utilizați nu clase concrete în codul programului, ci să manipulați obiecte abstracte la un nivel superior.

Scop

Definește o interfață pentru crearea unui obiect, dar lasă la latitudinea subclaselor să decidă pe ce clasă să se bazeze obiectul. O metodă din fabrică permite unei clase să delege crearea de subclase. Folosit când:

Structura

Avantaje

Dezavantaje

Exemple de cod

Swift

Exemplu rapid protocol Produs {     func getName () -> String } class ConcreteProductA : Product {     func getName () -> String {  return "ConcreteProductA" } } class ConcreteProductB : Product {     func getName () -> String { return "ConcreteProductB" } } Protocol Creator {     func factoryMethod () -> Product } class ConcreteCreatorA : Creator {     func factoryMethod () -> Product { return ConcreteProductA () } } clasa ConcreteCreatorB : Creator {     func factoryMethod () -> Product { return ConcreteProductB () } } let creatorA = ConcreteCreatorA () let creatorB = ConcreteCreatorB () lasă creatorii : [ Creator ] = [ creatorA , creatorB ] creatori . forEach {     let product = $ 0. factoryMethod ()     print ( product . getName ()) }

Python

Exemplu în Python # codificare: utf-8 """Tipuri de reglare""" clasă Cultură : """Cultură""" def __repr__ ( self ): return self . __str__ () Clasa Democratie ( Cultura ): def __str__ ( self ): return 'Democratie' clasa Dictatura ( Cultura ): def __str__ ( self ): return 'Dictatura' clasa Guvernare : """Guvernul însuși""" cultură = '' def __str__ ( self ): return self . cultura . __str__ () def __repr__ ( self ): return self . cultura . __repr__ () def set_culture ( self ): """Setați construirea pentru guvern: aceasta este metoda noastră din fabrică""" raise AttributeError ( 'Cultură neimplementată' ) clasa GovernmentA ( Government ): def set_culture ( self ): self . cultura = Democratie () clasa GovernmentB ( Government ): def set_culture ( self ): self . cultură = dictatură () g1 = GuvernA () g1 . set_culture () print ( str ( g1 )) g2 = GuvernulB () g2 . set_culture () print ( str ( g2 ))

Java

Exemplu Java interfață Produs { } clasa ConcreteProductA implementează Produs { } clasa ConcreteProductB implementează Produs { } abstract class Creator { public abstract Product factoryMethod (); } clasa ConcreteCreatorA extinde Creatorul { @Override public Product factoryMethod () { return new ConcreteProductA (); } } clasa ConcreteCreatorB extinde Creatorul { @Override public Product factoryMethod () { return new ConcreteProductB (); } } public class FactoryMethodExample { public static void main ( String [] args ) { // o serie de creatori Creator [] creators = { new ConcreteCreatorA (), new ConcreteCreatorB ()}; // repetă peste creatori și creează produse pentru ( Creator creator : creators ) { Product product = creator . factoryMethod (); Sistem . afară . printf ( "Creat {%s}\n" , produs .getClass ( )); } } }

Rezultatul muncii:

Creat {class ConcreteProductA} Creat {class ConcreteProductB}

C++

Exemplu în C++ #include <iostream> #include <șir> folosind namespace std ; struct Product { șir virtual getName () = 0 ; virtual ~ produs (){} }; struct ConcreteProductA : Product { șir getName (){ return "ConcreteProductA" ;} }; struct ConcreteProductB : Product { șir getName (){ return "ConcreteProductB" ;} }; struct Creator { Produs virtual * factoryMethod () = 0 ; }; struct ConcreteCreatorA : Creator { Produs * factoryMethod (){ return new ConcreteProductA ();} }; struct ConcreteCreatorB : Creator { Produs * factoryMethod (){ return new ConcreteProductB ();} }; int main () { ConcreteCreatorA CreatorA ; ConcreteCreatorB CreatorB ; // O serie de creatori Creator * creators [] = { & CreatorA , & CreatorB }; // Iterează peste creatori și creează produse pentru ( auto && creator : creatori ){ Produs * produs = creator -> factoryMethod (); cout << produs -> getName () << endl ; sterge produsul ; } returnează 0 ; }

Rezultatul lucrării:
ConcreteProductA
ConcreteProductB

C#

Exemplu în C# folosind System ; folosind System.Collections.Generic ; namespace Factory { public abstract class Product { public abstract string GetType (); } public class ConcreteProductA : Product { public override string GetType () { return "ConcreteProductA" ; } } public class ConcreteProductB : Product { public override string GetType () { return "ConcreteProductB" ; } } public abstract class Creator { public abstract Product FactoryMethod (); } public class ConcreteCreatorA : Creator { public override Product FactoryMethod () { return new ConcreteProductA (); } } public class ConcreteCreatorB : Creator { public override Product FactoryMethod () { return new ConcreteProductB (); } } public static class MainApp { public static void Main () { // o serie de creatori Creator [] creators = { new ConcreteCreatorA (), new ConcreteCreatorB () }; // repetă peste creatori și creează produse pentru fiecare ( Creator creator în creators ) { Product product = creator . FactoryMethod (); Consola . WriteLine ( „Creat {0}” , produs .GetType ( )); } // Așteptați Consola utilizatorului . citește (); } } }

JavaScript

Exemplu JavaScript ES5 var NewConcreteCreatorA = ()=>{ return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductA" };}} }; var NewConcreteCreatorB = ()=>{ return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductB" };}} }; var creators = [ NewConcreteCreatorA (), NewConcreteCreatorB ()]; creatori . map ( creator => console . log ( creator . factoryMethod (). getName ())); Exemplu JavaScript ES6 clasa Produs { GetName () {} } clasa ConcreteProductA extinde Product { GetName () { return 'ProductA' } } clasa ConcreteProductB extinde Product { GetName () { return 'ProductB' } } Class Creator { FactoryMethod () {} } clasa ConcreteCreatorA extinde Creatorul { FactoryMethod () { return new ConcreteProductA () } } clasa ConcreteCreatorB extinde Creator { FactoryMethod () { return new ConcreteProductB () } } // O serie de creatori const creators = [ new ConcreteCreatorA (), new ConcreteCreatorB () ] const products = [] // Iterați peste creatori și creați produse pentru ( let creators of creators ) { produse . push ( creator.FactoryMethod ( ). getName ( )) } consola . jurnal ( produse ) Exemplu în TypeScript interfață Produs { GetName () : șir } clasa ConcreteProductA implementează Product { public GetName () { return 'ProductA' } } clasa ConcreteProductB implementează Product { public GetName () { return 'ProductB' } } Creator de interfață { FactoryMethod () : Product } clasa ConcreteCreatorA implementează Creator { public FactoryMethod () { return new ConcreteProductA () } } clasa ConcreteCreatorB implementează Creator { public FactoryMethod () { return new ConcreteProductB () } } // O serie de creatori const creatori : Creator [] = [ nou ConcreteCreatorA (), nou ConcreteCreatorB () ] produse const : șir [] = [] // Iterați peste creatori și creați produse pentru ( let creators of creators ) { produse . push ( creator.FactoryMethod ( ). getName ( )) } consola . jurnal ( produse )

PHP5

Exemplu PHP <?php interface Product { public function GetName (); } clasa ConcreteProductA implementează Product { public function GetName () { return "ProductA" ; } } clasa ConcreteProductB implementează Product { public function GetName () { return "ProductB" ; } } interfață Creator { public function FactoryMethod (); } clasa ConcreteCreatorA implementează Creator { public function FactoryMethod () { return new ConcreteProductA (); } } clasa ConcreteCreatorB implementează Creator { public function FactoryMethod () { return new ConcreteProductB (); } } // O matrice de creatori $creators = array ( new ConcreteCreatorA (), new ConcreteCreatorB () ); // Iterează peste creatori și creează produse pentru fiecare ( $creators as $ creator ) { $produse [] = $creator -> FactoryMethod () -> getName (); } antet ( "content-type:text/plain" ); echo var_export ( $produse ); ?>

PHP5 versiune modernă

Versiunea prescurtată a modelului cel mai frecvent utilizat în PHP <?php /** * Class Animal, mai bine de 20 de ani de la prima ediție a cărții și acest model a evoluat puțin, * și acum folosește întotdeauna forma sa prescurtată */ abstract class Animal { // metoda din fabrică care returnează un obiect bazat pe tipul public static function initial ( $animal ) { return new $animal (); } voce abstractă a funcției publice (); } class Lion extinde Animal { public function voice () { echo 'Rrrrrrr eu sunt leul <br />' . PHP_EOL ; } } class Cat extins Animal { public function voice () { echo 'Miau, miau, eu sunt pisicuta <br />' . PHP_EOL ; } } $animal1 = Animal :: initial ( 'Leul' ); $animal2 = Animal :: initial ( 'Pisica' ); $animal1 -> voce (); $animal2 -> voce ();

Delphi

exemplu Delphi program FactoryMethod ; {$APPTYPE CONSOLE} folosește SysUtils ; tip // Produs TProduct = clasă ( TObject ) funcţie publică GetName : şir ; virtual ; abstract ; sfârşitul ; // ConcreteProductA TConcreteProductA = clasă ( TPProduct ) funcție publică GetName : șir ; suprascrie ; sfârşitul ; // ConcreteProductB TConcreteProductB = clasă ( TPProduct ) funcție publică GetName : șir ; suprascrie ; sfârşitul ; // Creator TCreator = clasă ( TObject ) funcţie publică FactoryMethod : TProduct ; virtual ; abstract ; sfârşitul ; // ConcreteCreatorA TConcreteCreatorA = clasă ( TCreator ) funcție publică FactoryMethod : TProduct ; suprascrie ; sfârşitul ; // ConcreteCreatorB TConcreteCreatorB = clasă ( TCreator ) funcție publică FactoryMethod : TProduct ; suprascrie ; sfârşitul ; {ConcreteProductA} funcția TConcreteProductA . GetName : șir ; start Rezultat := 'ConcreteProductA' ; sfârşitul ; {ConcreteProductB} funcția TConcreteProductB . GetName : șir ; start Rezultat := 'ConcreteProductB' ; sfârşitul ; Funcția { ConcreteCreatorA } TConcreteCreatorA . FactoryMethod : TProduct ; începe Rezultatul := TConcreteProductA . a crea ; sfârşitul ; Funcția { ConcreteCreatorB } TConcreteCreatorB . FactoryMethod : TProduct ; începe Rezultatul := TConcreteProductB . a crea ; sfârşitul ; const Count = 2 ; var Creatori : matrice [ 1 .. Count ] din TCreator ; Produs : TProduct ; I : Număr întreg ; begin // O serie de creatori Creatori [ 1 ] := TConcreteCreatorA . a crea ; Creatori [ 2 ] := TConcreteCreatorB . a crea ; // Iterează peste creatori și creează produse pentru I := 1 to Count do begin Product := Creators [ I ] . FactoryMethod ; WriteLn ( Produs . GetName ) ; produs . Gratuit ; sfârşitul ; pentru I := 1 to Count do Creators [ I ] . Gratuit ; Readln ; sfârşitul . Exemplu Delphi (constructori virtuali) program FactoryMethod ; {$APPTYPE CONSOLE} folosește SysUtils ; tip // Product TProduct = class ( TObject ) private SubName : șir ; funcția publică GetName : șir ; virtual ; abstract ; funcția GetFullName : șir ; constructor Create ; virtual ; abstract ; sfârşitul ; TProductClass = clasa de TProduct ; // ConcreteProductA TConcreteProductA = clasă ( TPProduct ) funcție publică GetName : șir ; suprascrie ; constructor Create ; suprascrie ; sfârşitul ; // ConcreteProductB TConcreteProductB = clasă ( TPProduct ) funcție publică GetName : șir ; suprascrie ; constructor Create ; suprascrie ; sfârşitul ; Funcția { TProduct} TProduct . GetFullName : șir ; start Rezultat := GetName + ' : ' + SubName ; sfârşitul ; { ConcreteProductA } constructor TConcreteProductA . a crea ; începe moștenit ; SubName := 'Subnume produs A' ; sfârşitul ; funcția TConcreteProductA . GetName : șir ; start Rezultat := 'ConcreteProductA' ; sfârşitul ; { ConcreteProductB } constructor TConcreteProductB . a crea ; începe moștenit ; SubName := 'Subnume produs B' ; sfârşitul ; funcția TConcreteProductB . GetName : șir ; start Rezultat := 'ConcreteProductB' ; sfârşitul ; const Count = 2 ; var Creatori : matrice [ 1 .. Count ] din TProductClass ; Produs : TProduct ; I : Număr întreg ; begin // O serie de creatori Creatori [ 1 ] := TConcreteProductA ; Creatori [ 2 ] := TConcreteProductB ; // Iterează peste creatori și creează produse pentru I := 1 to Count do begin Product := Creators [ I ] . a crea ; WriteLn ( Produs . GetFullName ) ; produs . Gratuit ; sfârşitul ; Readln ; sfârşitul .

Action Script 3.0

Exemplu în Action Script 3.0 protected class Creator { protected function factoryMethod () : Produs { return null ; } public function someFunction () : void { var _product : Produs = factoryMethod (); _produs . doSome (); } } public class ConcreteCreatorA extins Creator { override protected function factoryMethod () : Produs { return new ConcreteProductA (); } } public class ConcreteCreatorB extinde Creator { override protected function factoryMethod () : Produs { return new ConcreteProductB (); } } interfață publică Produs { function doSome () : void {} } clasa internă ConcreteProductA implementează Product { public function doSome () : void {} } clasa internă ConcreteProductB implementează Product { public function doSome () : void {} } // IMPLEMENTARE public class Main { public function Main () { var _creatorA : ConcreteCreatorA = new ConcreteCreatorA (); _creatorA . someFunction (); var _creatorB : ConcreteCreatorB = nou ConcreteCreatorB (); _creatorB . someFunction (); } }

scala

exemplu Scala clasa abstracta _ _ def getName : șir } clasa abstracta _ _ def getProduct : AbstractProduct } clasa Bere extinde AbstractProduct { override def getName : String = "Bere" } clasa Vin extinde AbstractProduct { suprascrie def getName : String = "Wine" } clasa BeerCreator extinde AbstractCreator { suprascrie def getProduct : AbstractProduct = bere nouă } clasa WineCreator extinde AbstractCreator { suprascrie def getProduct : AbstractProduct = vin nou } obiect Test { private def printProductName ( creator : AbstractCreator ) : Unit = println ( creator . getProduct . getName ) def main ( args : Array [ String ]) : Unit = printProductName ( nou BeerCreator ) printProductName ( nou WineCreator ) }

Rezultatul muncii:
Creat: Vin Creat: Bere

Ruby

Exemplu în Ruby module FactoryMethod # Clasa de produs Product attr_reader : productType def initialize @productType = nil end end # ConcreteProductA class ConcreteProductA < Product attr_reader : productType def initialize @productType = "ConcreteProductA" end end # ConcreteProductB class ConcreteProductB < Product attr_reader : productType def initialize @productType = "ConcreteProductB" end end # Creator class Creator def factoryMethod Product . sfârşit nou _ # ConcreteCreatorA class ConcreteCreatorA < Creator def factoryMethod ConcreteProductA . sfârşit nou _ # ConcreteCreatorB class ConcreteCreatorB < Creator def factoryMethod ConcreteProductB . sfârşit nou sfârşit sfârşit # Modulul client Clientul include FactoryMethod creatori = [ ConcreteCreatorA . nou , ConcreteCreatorB . nou ] creatori . fiecare face | creator | pune " #{ creator . class } create Product: \t #{ creator . factoryMethod . productType } " end # => FactoryMethod::ConcreteCreatorA create Product: ConcreteProductA # => FactoryMethod::ConcreteCreatorB create Product: ConcreteProductB end

Literatură

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Tehnici de proiectare orientată pe obiecte. Design Patterns = Design Patterns : Elemente de software reutilizabil orientat pe obiecte. - Sankt Petersburg. : „Petru” , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (și ISBN 5-272-00355-1 )