Fabriksmetod (designmönster)
Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från
versionen som granskades den 11 september 2018; kontroller kräver
32 redigeringar .
fabriksmetod |
---|
Fabriksmetod |
Fabriksmetod |
Sorts |
Alstrande |
Ändamål |
Att skapa objekt av olika typer med ett gränssnitt |
fördelar |
Skapande av objekt, oavsett deras typ och komplexiteten i skapelseprocessen. |
Minus |
Även för ett enda objekt måste du skapa en lämplig fabrik, vilket ökar koden. |
Beskrivs i Design Patterns |
Ja |
En fabriksmetod ( eng. Factory Method ), eller en virtuell konstruktor ( eng. Virtual Constructor ) är ett genererande designmönster som förser underklasser (underklasser, underklasser) med ett gränssnitt för att skapa instanser av en viss klass. Vid skapandet kan efterkommande bestämma vilken klass som ska skapas. Med andra ord, den här mallen delegerar skapandet av objekt till avkomlingarna till den överordnade klassen. Detta gör att du inte kan använda konkreta klasser i programkoden, utan att manipulera abstrakta objekt på en högre nivå.
Syfte
Definierar ett gränssnitt för att skapa ett objekt, men överlåter till underklasser att bestämma vilken klass som objektet ska baseras på. En fabriksmetod tillåter en klass att delegera skapandet av underklasser. Används när:
- klassen vet inte i förväg vilka objekt av vilka underklasser den behöver skapa.
- en klass är utformad så att objekten den skapar specificeras av underklasser.
- klassen delegerar sitt ansvar till en av flera hjälpunderklasser, och det är planerat att lokalisera kunskapen om vilken klass som tar över dessa ansvarsområden.
Struktur
- produkt - produkt
- definierar ett gränssnitt för objekt skapade med en abstrakt metod;
- ConcreteProduct - en specifik produkt
- implementerar produktgränssnittet ;
- skapare _
- deklarerar en fabriksmetod som returnerar ett objekt av typen Produkt . Kan också innehålla en "standard" implementering av denna metod;
- kan anropa en fabriksmetod för att skapa ett objekt av typen Produkt ;
- ConcreteCreator - specifik skapare
- åsidosätter fabriksmetoden för att skapa och returnera ett objekt av klassen ConcreteProduct .
Fördelar
- låter dig göra koden för att skapa objekt mer universell, inte knuten till specifika klasser (ConcreteProduct), utan fungerar endast med ett gemensamt gränssnitt (Produkt);
- låter dig upprätta en relation mellan parallella klasshierarkier.
Nackdelar
- behovet av att skapa en Creator-efterträdare för varje ny typ av produkt (ConcreteProduct).
Kodexempel
Swift
Snabbt exempel
protokoll Produkt {
func getName () -> String
}
klass ConcreteProductA : Product {
func getName () -> String { return "ConcreteProductA" }
}
class ConcreteProductB : Product {
func getName () -> String { return "ConcreteProductB" }
}
protokoll Skapare {
func factoryMethod () -> Produkt
}
class ConcreteCreatorA : Creator {
func factoryMethod () -> Product { return ConcreteProductA () }
}
class ConcreteCreatorB : Creator {
func factoryMethod () -> Product { return ConcreteProductB () }
}
låt skapareA = ConcreteCreatorA ()
låt skapareB = ConcreteCreatorB ()
låt skapare : [ Skapare ] = [ skapareA , skapareB ]
skapare . forEach {
låt produkt = $ 0. factoryMethod ()
print ( produkt . getName ())
}
Python
Exempel i
Python
# kodning: utf-8
"""Tuning typer"""
klass Kultur :
"""Kultur"""
def __repr__ ( själv ):
returnera själv . __str__ ()
klass Demokrati ( Kultur ):
def __str__ ( själv ):
returnera 'Demokrati'
klass Diktatur ( Kultur ):
def __str__ ( själv ):
returnera 'Diktatur'
klass Regering :
"""Regeringen själv"""
kultur = ''
def __str__ ( själv ):
returnera själv . kultur . __str__ ()
def __repr__ ( själv ):
returnera själv . kultur . __repr__ ()
def set_culture ( self ):
"""Ställ in bygg till regeringen: detta är vår fabriksmetod"""
raise AttributeError ( 'Not Implemented Culture' )
klass GovernmentA ( Regering ):
def set_culture ( self ):
själv . kultur = demokrati ()
klass RegeringB ( Regering ):
def set_culture ( själv ):
själv . kultur = diktatur ()
g1 = RegeringA ()
g1 . set_culture ()
print ( str ( g1 ))
g2 = RegeringB ()
g2 . set_culture ()
print ( str ( g2 ))
Java
Java exempel
gränssnitt Produkt { }
klass ConcreteProductA implementerar produkt { }
klass ConcreteProductB implementerar produkt { }
abstrakt klass Skapare {
public abstract Product factoryMethod ();
}
class ConcreteCreatorA utökar Creator {
@Override
public Product factoryMethod () { return new ConcreteProductA (); }
}
class ConcreteCreatorB utökar Creator {
@Override
public Product factoryMethod () { return new ConcreteProductB (); }
}
public class FactoryMethodExample {
public static void main ( String [] args ) {
// en array av skapare
Skapare [] skapare = { new ConcreteCreatorA (), new ConcreteCreatorB ()};
// iterera över kreatörer och skapa produkter
för ( Creator creator : creators ) {
Product product = creator . fabriksmetod ();
System . ut . printf ( "Skapade {%s}\n" , produkt .getClass ( ));
}
}
}
Resultat av arbetet:
Skapade {class ConcreteProductA}
Skapade {class ConcreteProductB}
C++
Exempel i
C++
#include <iostream>
#inkludera <sträng>
använder namnutrymme std ;
struktur produkt {
virtuell sträng getName () = 0 ;
virtuell ~ Produkt (){}
};
struct ConcreteProductA : Produkt {
string getName (){ return "ConcreteProductA" ;}
};
struct ConcreteProductB : Produkt {
string getName (){ return "ConcreteProductB" ;}
};
struct Creator {
virtuell produkt * factoryMethod () = 0 ;
};
struct ConcreteCreatorA : Creator {
Produkt * factoryMethod (){ returnera ny ConcreteProductA ();}
};
struct ConcreteCreatorB : Creator {
Produkt * factoryMethod (){ returnera ny ConcreteProductB ();}
};
int main ()
{
ConcreteCreatorA CreatorA ;
ConcreteCreatorB CreatorB ;
// En mängd skapare
Skapare * skapare [] = { & SkapareA , & SkapareB };
// Iterera över kreatörer och skapa produkter
för ( auto && creator : creators ){
Produkt * produkt = skapare -> factoryMethod ();
cout << produkt -> getName () << endl ;
ta bort produkt ;
}
returnera 0 ;
}
Resultat av arbetet:
ConcreteProductA
ConcreteProductB
C#
Exempel i
C#
använder System ;
använder System.Collections.Generic ;
namnutrymme 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 ()
{
// an array of creators
Creator [] creators = { new ConcreteCreatorA (), new ConcreteCreatorB () };
// upprepa över kreatörer och skapa produkter
för varje ( Creator creator in creators )
{
Product product = creator . FactoryMethod ();
Konsol . WriteLine ( "Created {0}" , produkt .GetType ( ));
}
// Vänta på
användarkonsolen . läs ();
}
}
}
JavaScript
JavaScript ES5 exempel
var NewConcreteCreatorA = ()=>{
return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductA" };}}
};
var NewConcreteCreatorB = ()=>{
return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductB" };}}
};
var creators = [ NewConcreteCreatorA (), NewConcreteCreatorB ()];
skapare . map ( skapare => konsol . logg ( skapare . factoryMethod (). getName ()));
JavaScript ES6 exempel
klassprodukt { GetName ( ) {} }
klass ConcreteProductA utökar produkt {
GetName () {
return 'ProductA'
}
}
klass ConcreteProductB utökar produkt {
GetName () {
return 'ProductB'
}
}
klass Skapare {
FactoryMethod () {}
}
klass ConcreteCreatorA utökar Creator {
FactoryMethod () {
return new ConcreteProductA ()
}
}
klass ConcreteCreatorB utökar Creator {
FactoryMethod () {
return new ConcreteProductB ()
}
}
// En rad kreatörer
const creators = [ new ConcreteCreatorA (), new ConcreteCreatorB () ]
const products = []
// Iterera över kreatörer och skapa produkter
för ( låt skapare av kreatörer ) {
produkter . push ( creator.FactoryMethod ( ). getName ( )) }
konsol . log ( produkter )
Exempel i
TypeScript
gränssnitt Produkt {
GetName () : string
}
klass ConcreteProductA implementerar produkt {
public GetName () {
return 'ProductA'
}
}
class ConcreteProductB implementerar produkt {
public GetName () {
return 'ProductB'
}
}
gränssnitt Skapare {
FactoryMethod () : Produkt
}
class ConcreteCreatorA implementerar Creator {
public FactoryMethod () {
return new ConcreteProductA ()
}
}
class ConcreteCreatorB implementerar Creator {
public FactoryMethod () {
return new ConcreteProductB ()
}
}
// En rad kreatörer
const creators : Creator [] = [ new ConcreteCreatorA (), new ConcreteCreatorB () ]
const products : string [] = []
// Iterera över kreatörer och skapa produkter
för ( låt skapare av kreatörer ) {
produkter . push ( creator.FactoryMethod ( ). getName ( )) }
konsol . log ( produkter )
PHP5
PHP exempel
<?php
-gränssnitt Produkt {
offentlig funktion GetName ();
}
class ConcreteProductA implementerar Product {
public function GetName () { return "ProductA" ; }
}
class ConcreteProductB implementerar Product {
public function GetName () { return "ProductB" ; }
}
gränssnitt Creator {
public function FactoryMethod ();
}
class ConcreteCreatorA implementerar Creator {
public function FactoryMethod () { return new ConcreteProductA (); }
}
class ConcreteCreatorB implementerar Creator {
public function FactoryMethod () { return new ConcreteProductB (); }
}
// En array av skapare
$creators = array ( new ConcreteCreatorA (), new ConcreteCreatorB () );
// Iterera över skapare och skapa produkter för varje
( $creators som $ creator ) { $products [] = $creator -> FactoryMethod () -> getName (); }
header ( "content-type:text/plain" );
echo var_export ( $produkter );
?>
PHP5 modern version
Förkortad version av det mönster som oftast används i
PHP
<?php
/**
* Class Animal, mer än 20 år sedan första upplagan av boken och detta mönster har utvecklats lite,
* och använder nu alltid sin förkortade form
*/
abstrakt klass Animal
{
// fabriksmetod som returnerar en objekt baserat på typen
public static function initial ( $animal )
{
return new $animal ();
}
abstrakt offentlig funktion röst ();
}
class Lion utökar Animal
{
public function voice ()
{
echo 'Rrrrrrr jag är lejonet <br />' . PHP_EOL ;
}
}
class Cat extends Animal
{
public function voice ()
{
echo 'Mjau, jaja jag är kattungen <br />' . PHP_EOL ;
}
}
$animal1 = Djur :: initial ( 'Lion' );
$animal2 = Djur :: initial ( 'Katt' );
$djur1 -> röst ();
$djur2 -> röst ();
Delphi
Delphi exempel
program FactoryMethod ;
{$APPTYPE KONSOL}
använder
SysUtils ;
typ
// Produkt
TProduct = class ( TObject )
offentlig
funktion GetName : string ; virtuell ; abstrakt ;
slut ;
// ConcreteProductA
TConcreteProductA = klass ( TProduct )
offentlig
funktion GetName : string ; åsidosätta ;
slut ;
// ConcreteProductB
TConcreteProductB = klass ( TProduct )
offentlig
funktion GetName : string ; åsidosätta ;
slut ;
// Skapare
TCreator = klass ( TObject )
offentlig
funktion FactoryMethod : TProduct ; virtuell ; abstrakt ;
slut ;
// ConcreteCreatorA
TConcreteCreatorA = klass ( TCreator )
offentlig
funktion FactoryMethod : TProduct ; åsidosätta ;
slut ;
// ConcreteCreatorB
TConcreteCreatorB = klass ( TCreator )
offentlig
funktion FactoryMethod : TProduct ; åsidosätta ;
slut ;
{ConcreteProductA}
-funktionen TConcreteProductA . GetName : string ;
börja
Resultat := 'ConcreteProductA' ;
slut ;
{ConcreteProductB}
-funktionen TConcreteProductB . GetName : string ;
börja
Resultat := 'ConcreteProductB' ;
slut ;
{ConcreteCreatorA}
-funktionen TConcreteCreatorA . FactoryMethod : TProduct ;
börja
Resultat := TConcreteProductA . skapa ;
slut ;
{ConcreteCreatorB}
-funktionen TConcreteCreatorB . FactoryMethod : TProduct ;
börja
Resultat := TKonkretproduktB . skapa ;
slut ;
const
Count = 2 ;
var
Creators : array [ 1 .. Count ] av TCreator ;
Produkt : TProdukt ;
I : Heltal ;
börja
// En mängd skapare
Skapare [ 1 ] := TConcreteCreatorA . skapa ;
Skapare [ 2 ] := TConcreteCreatorB . skapa ;
// Iterera över kreatörer och skapa produkter
för I : = 1 to Count start
Product
:= Creators [ I ] . FactoryMethod ; WriteLn ( Produkt . GetName ) ; produkt . Gratis ; slut ;
för I := 1 till Count do
Creators [ I ] . Gratis ;
Läsln ;
slut .
Delphi - exempel (virtuella konstruktörer)
program FactoryMethod ;
{$APPTYPE KONSOL}
använder
SysUtils ;
typ
// Produkt
TProduct = class ( TObject )
private
SubName : string ;
offentlig
funktion GetName : string ; virtuell ; abstrakt ;
function GetFullName : string ;
konstruktör Skapa ; virtuell ; abstrakt ;
slut ;
TProductClass = klass av TProduct ;
// ConcreteProductA
TConcreteProductA = klass ( TProduct )
offentlig
funktion GetName : string ; åsidosätta ;
konstruktör Skapa ; åsidosätta ;
slut ;
// ConcreteProductB
TConcreteProductB = klass ( TProduct )
offentlig
funktion GetName : string ; åsidosätta ;
konstruktör Skapa ; åsidosätta ;
slut ;
{ TProduct}
-funktionen TProduct . GetFullName : string ;
börja
Resultat := GetName + ' : ' + SubName ;
slut ;
{ ConcreteProductA }
konstruktör TConcreteProductA . skapa ;
börja
ärvt ;
SubName := 'Produkt Ett undernamn' ;
slut ;
funktion TKonkretProduktA . GetName : string ;
börja
Resultat := 'ConcreteProductA' ;
slut ;
{ConcreteProductB}
-konstruktör TConcreteProductB . skapa ;
börja
ärvt ;
SubName := 'Produkt B undernamn' ;
slut ;
funktion TKonkretProduktB . GetName : string ;
börja
Resultat := 'ConcreteProductB' ;
slut ;
const
Count = 2 ;
var
Creators : array [ 1 .. Count ] av TProductClass ;
Produkt : TProdukt ;
I : Heltal ;
börja
// En rad skapare
Skapare [ 1 ] := TConcreteProductA ;
Skapare [ 2 ] := TConcreteProductB ;
// Iterera över kreatörer och skapa produkter
för I : = 1 to Count start
Product
:= Creators [ I ] . skapa ; WriteLn ( Produkt . GetFullName ) ; produkt . Gratis ; slut ;
Läsln ;
slut .
Action Script 3.0
Exempel i
Action Script 3.0
protected class Creator
{
protected function factoryMethod () : Produkt { return null ; }
public function someFunction () : void
{
var _product : Product = factoryMethod ();
_produkt . doSome ();
}
}
public class ConcreteCreatorA utökar Creator
{
override protected function factoryMethod () : Produkt
{
returnera ny ConcreteProductA ();
}
}
public class ConcreteCreatorB utökar Creator
{
override protected function factoryMethod () : Produkt
{
returnera ny ConcreteProductB ();
}
}
offentligt gränssnitt Produkt
{
function doSome () : void {}
}
intern klass ConcreteProductA implementerar produkt
{
public function doSome () : void {}
}
intern klass ConcreteProductB implementerar produkt
{
public function doSome () : void {}
}
// GENOMFÖRANDE
public class Main
{
public function Main ()
{
var _creatorA : ConcreteCreatorA = new ConcreteCreatorA ();
_skapareA . someFunction ();
var _creatorB : ConcreteCreatorB = new ConcreteCreatorB ();
_skapareB . someFunction ();
}
}
scala
Scala exempel
abstrakt klass _ _
def getName : String
}
abstrakt klass _ _
def getProduct : AbstractProduct
}
klass Öl förlänger SammanfattningProduct {
override def getName : String = "Öl"
}
class Wine extends AbstractProduct {
override def getName : String = "Wine"
}
klass BeerCreator utökar AbstractCreator {
åsidosätt def getProduct : AbstractProduct = new Beer
}
klass WineCreator utökar AbstractCreator {
åsidosätt def getProduct : AbstractProduct = nytt vin
}
objekt Test {
privat def printProductName ( skapare : AbstractCreator ) : Unit =
println ( skapare . getProduct . getName )
def main ( args : Array [ String ] ) : Unit =
printProductName ( new BeerCreator )
printProductName ( new WineCreator )
}
Resultat av arbetet:
Skapad: Vin Skapad: Öl
Ruby
Exempel i
Ruby
modul FactoryMethod
#
Produktklass Product
attr_reader :productType
def initialize
@productType = noll
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
Produkt . nytt
slutslut
_
# ConcreteCreatorA
klass ConcreteCreatorA < Creator
def factoryMethod
ConcreteProductA . nytt
slutslut
_
# ConcreteCreatorB
klass ConcreteCreatorB < Creator
def factoryMethod
ConcreteProductB . ny
ände
ände
_
#
Klientmodul Klienten
inkluderar FactoryMethod
skapare = [ ConcreteCreatorA . ny , ConcreteCreatorB . ny ]
skapare . varje gör | skapare |
sätter " #{ creator . class } create Product: \t #{ creator . factoryMethod . productType } " slut
# => FactoryMethod::ConcreteCreatorA skapa Produkt: ConcreteProductA
# => FactoryMethod::ConcreteCreatorB skapa Produkt: ConcreteProductB
slut
Litteratur
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Tekniker för objektorienterad design. Designmönster = Designmönster : Element av återanvändbar objektorienterad programvara. - St Petersburg. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (även ISBN 5-272-00355-1 )