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:
- clasa nu știe dinainte ce obiecte din ce subclase trebuie să creeze.
- o clasă este proiectată astfel încât obiectele pe care le creează să fie specificate prin subclase.
- clasa își deleagă responsabilitățile uneia dintre mai multe subclase de ajutor și este planificată să localizeze cunoștințele despre care clasă preia aceste responsabilități.
Structura
- produs - produs
- definește o interfață pentru obiectele create printr-o metodă abstractă;
- ConcreteProduct - un produs specific
- implementează interfața Produsului ;
- creator _
- declară o metodă din fabrică care returnează un obiect de tip Product . Poate conține, de asemenea, o implementare „implicit” a acestei metode;
- poate apela o metodă din fabrică pentru a crea un obiect de tip Product ;
- ConcreteCreator - creator specific
- suprascrie metoda din fabrică pentru a crea și returna un obiect din clasa ConcreteProduct .
Avantaje
- vă permite să faceți codul pentru crearea obiectelor mai universal, nefiind legat de clase specifice (ConcreteProduct), ci operând doar cu o interfață comună (Product);
- vă permite să stabiliți o relație între ierarhiile de clasă paralele.
Dezavantaje
- necesitatea de a crea un succesor Creator pentru fiecare tip nou de produs (ConcreteProduct).
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 )