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:

Struktur

Fördelar

Nackdelar

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 )