Tovární metoda (návrhový vzor)

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 11. září 2018; kontroly vyžadují 32 úprav .
tovární metoda
Tovární metoda

Tovární metoda
Typ Generování
Účel Vytvářet objekty různých typů s jedním rozhraním
profesionálové Tvorba objektů bez ohledu na jejich typy a složitost procesu tvorby.
Mínusy I pro jeden objekt je potřeba vytvořit vhodnou továrnu, která zvyšuje kód.
Popsáno v Návrhové vzory Ano

Tovární metoda ( angl.  Factory Method ), neboli virtuální konstruktor ( angl.  Virtual Constructor ) je generující návrhový vzor , ​​který poskytuje podtřídám (podtřídám, podtřídám) rozhraní pro vytváření instancí určité třídy. V době vytvoření mohou potomci určit, kterou třídu vytvořit. Jinými slovy, tato šablona deleguje vytváření objektů na potomky nadřazené třídy. To vám umožňuje používat v kódu programu nikoli konkrétní třídy, ale manipulovat s abstraktními objekty na vyšší úrovni.

Účel

Definuje rozhraní pro vytváření objektu, ale ponechává na podtřídách, aby rozhodly, na které třídě bude objekt založen. Tovární metoda umožňuje třídě delegovat vytváření podtříd. Používá se, když:

Struktura

Výhody

Nevýhody

Příklady kódu

Swift

Rychlý příklad protokol Produkt {     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 () } } class ConcreteCreatorB : Creator {     func factoryMethod () -> Product { return ConcreteProductB () } } nechť tvůrceA = ConcreteCreatorA () nechť tvůrceB = ConcreteCreatorB () nechat tvůrce : [ tvůrce ] = [ tvůrceA , tvůrceB ] tvůrci . forEach {     let product = $ 0. factoryMethod ()     print ( product . getName ()) }

Python

Příklad v Pythonu # kódování: utf-8 """Typy ladění""" class Culture : """Culture""" def __repr__ ( self ): return self . __str__ () class Democracy ( Culture ): def __str__ ( self ): return 'Demokracie' class Dictatorship ( Culture ): def __str__ ( self ): return 'Dictaturship' class Government : """Sama vláda""" kultura = '' def __str__ ( self ): návrat self . kultura . __str__ () def __repr__ ( self ): return self . kultura . __repr__ () def set_culture ( self ): """Nastavit sestavení na vládu: toto je naše tovární metoda""" zvýšit AttributeError ( 'Not Implemented Culture' ) class GovernmentA ( Government ): def set_culture ( self ): self . kultura = demokracie () class GovernmentB ( Government ): def set_culture ( self ): self . kultura = diktatura () g1 = VládaA () g1 . set_culture () print ( str ( g1 )) g2 = VládaB () g2 . set_culture () print ( str ( g2 ))

Java

Příklad Java rozhraní Produkt { } class ConcreteProductA implementuje produkt { } class ConcreteProductB implementuje produkt { } abstract class Creator { public abstract Product factoryMethod (); } class ConcreteCreatorA extends Creator { @Override public Product factoryMethod () { return new ConcreteProductA (); } } class ConcreteCreatorB extends Creator { @Override public Product factoryMethod () { return new ConcreteProductB (); } } public class FactoryMethodExample { public static void main ( String [] args ) { // pole tvůrců Creator [] creators = { new ConcreteCreatorA (), new ConcreteCreatorB ()}; // iterujte přes tvůrce a vytvořte produkty pro ( Creator creator : creators ) { Product product = creator . tovární metoda (); Systém . ven . printf ( "Vytvořeno {%s}\n" , produkt .getClass ( )); } } }

Výsledek práce:

Vytvořeno {class ConcreteProductA} Vytvořeno {class ConcreteProductB}

C++

Příklad v C++ #include <iostream> #include <řetězec> pomocí jmenného prostoru std ; struct Produkt { virtuální řetězec getName () = 0 ; virtuální ~ Produkt (){} }; struct ConcreteProductA : Product { string getName (){ return "ConcreteProductA" ;} }; struct ConcreteProductB : Product { string getName (){ return "ConcreteProductB" ;} }; struct Creator { virtuální produkt * factoryMethod () = 0 ; }; struct ConcreteCreatorA : Creator { Produkt * tovární metoda (){ vrátit nový betonový produktA ( );} }; struct ConcreteCreatorB : Creator { Produkt * tovární metoda (){ vrátit nový betonový produktB ( );} }; int main () { ConcreteCreatorA CreatorA ; ConcreteCreatorB CreatorB ; // Pole tvůrců Creator * creators [] = { & CreatorA , & CreatorB }; // Iterujte autory a vytvářejte produkty pro ( auto && creator : creators ){ Produkt * produkt = tvůrce -> factoryMethod (); cout << produkt -> getName () << endl ; odstranit produkt ; } návrat 0 ; }

Výsledek práce:
ConcreteProductA
ConcreteProductB

C#

Příklad v C# pomocí System ; pomocí System.Collections.Generic ; jmenný prostor 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 () { // pole tvůrců Creator [] creators = { new ConcreteCreatorA (), new ConcreteCreatorB () }; // iterujte přes tvůrce a vytvářejte produkty foreach ( Creator creator in creators ) { Product product = creator . Tovární metoda (); Konzole . WriteLine ( "Vytvořeno {0}" , produkt .GetType ( )); } // Počkejte na uživatelskou konzoli . číst (); } } }

JavaScript

Příklad JavaScript ES5 var NewConcreteCreatorA = ()=>{ return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductA" };}} }; var NewConcreteCreatorB = ()=>{ return { factoryMethod : ()=>{ return { getName : ()=> "ConcreteProductB" };}} }; var creators = [ NewConcreteCreatorA (), NewConcreteCreatorB ()]; tvůrci . mapa ( tvůrce => konzole . protokol ( tvůrce . factoryMethod (). getName ())); Příklad JavaScript ES6 třída Produkt { GetName () {} } class ConcreteProductA rozšiřuje produkt { GetName () { return 'ProductA' } } class ConcreteProductB rozšiřuje produkt { GetName () { return 'ProductB' } } class Creator { FactoryMethod () {} } class ConcreteCreatorA rozšiřuje Creator { FactoryMethod () { return new ConcreteProductA () } } class ConcreteCreatorB rozšiřuje Creator { FactoryMethod () { return new ConcreteProductB () } } // Pole tvůrců const creators = [ new ConcreteCreatorA (), new ConcreteCreatorB () ] const products = [] // Iterujte přes tvůrce a vytvořte produkty pro ( nechte tvůrce tvůrců ) { products . push ( creator.FactoryMethod ( ). getName ( )) } konzole . log ( produkty ) Příklad v TypeScriptu rozhraní Produkt { GetName () : string } class ConcreteProductA implementuje produkt { public GetName () { return 'ProductA' } } class ConcreteProductB implementuje produkt { public GetName () { return 'ProductB' } } tvůrce rozhraní { FactoryMethod () : Produkt } class ConcreteCreatorA implementuje Creator { public FactoryMethod () { return new ConcreteProductA () } } class ConcreteCreatorB implementuje Creator { public FactoryMethod () { return new ConcreteProductB () } } // Pole tvůrců const creators : Creator [] = [ new ConcreteCreatorA (), new ConcreteCreatorB () ] const products : string [] = [] // Iterujte přes tvůrce a vytvořte produkty pro ( nechte tvůrce tvůrců ) { products . push ( creator.FactoryMethod ( ). getName ( )) } konzole . log ( produkty )

PHP5

Příklad PHP <?php rozhraní Produkt { public function GetName (); } class ConcreteProductA implementuje Produkt { public function GetName () { return "ProductA" ; } } class ConcreteProductB implementuje Produkt { public function GetName () { return "ProductB" ; } } interface Creator { public function FactoryMethod (); } class ConcreteCreatorA implementuje Creator { public function FactoryMethod () { return new ConcreteProductA (); } } class ConcreteCreatorB implementuje Creator { public function FactoryMethod () { return new ConcreteProductB (); } } // Pole tvůrců $creators = array ( new ConcreteCreatorA (), new ConcreteCreatorB () ); // Iterace přes tvůrce a vytváření produktů foreach ( $creators jako $creator ) { $products [] = $creator -> FactoryMethod () -> getName (); } záhlaví ( "typ-obsahu:text/prostý" ); echo var_export ( $products ); ?>

Moderní verze PHP5

Zkrácená verze vzoru nejčastěji používaného v PHP <?php /** * Class Animal, více než 20 let od prvního vydání knihy a tento vzor se trochu vyvinul, * a nyní vždy používejte jeho zkrácenou formu */ abstract class Animal { // tovární metoda, která vrací objekt založený na typu public static function initial ( $animal ) { return new $animal (); } abstraktní hlas veřejné funkce (); } class Lion extends Animal { public function voice () { echo 'Rrrrrrr i\'m the lion <br />' . PHP_EOL ; } } class Cat extends Animal { public function voice () { echo 'Mňau, mňau, já jsem kočička <br />' . PHP_EOL ; } } $animal1 = Animal :: initial ( 'Lev' ); $animal2 = Animal :: initial ( 'Kočka' ); $animal1 -> hlas (); $animal2 -> hlas ();

Delphi

Příklad Delphi program FactoryMethod ; {$APPTYPE KONZOLE} používá SysUtils ; typ // Produkt TProdukt = class ( TObject ) public function GetName : string ; virtuální ; abstraktní ; konec ; // ConcreteProductA TConcreteProductA = class ( TProduct ) public function GetName : string ; přepsat ; konec ; // ConcreteProductB TConcreteProductB = class ( TProduct ) public function GetName : string ; přepsat ; konec ; // Creator TCreator = class ( TObject ) public function FactoryMethod : TProduct ; virtuální ; abstraktní ; konec ; // ConcreteCreatorA TConcreteCreatorA = class ( TCreator ) veřejná funkce FactoryMethod : TProduct ; přepsat ; konec ; // ConcreteCreatorB TConcreteCreatorB = class ( TCreator ) public function FactoryMethod : TProduct ; přepsat ; konec ; { ConcreteProductA } funkce TConcreteProductA . GetName : string ; begin Vysledek := 'ConcreteProductA' ; konec ; { ConcreteProductB } funkce TConcreteProductB . GetName : string ; begin Vysledek := 'ConcreteProductB' ; konec ; { ConcreteCreatorA } funkce TConcreteCreatorA . Tovární metoda : TProdukt ; begin Vysledek := TConcreteProductA . vytvořit ; konec ; { ConcreteCreatorB } funkce TConcreteCreatorB . Tovární metoda : TProdukt ; begin Vysledek := TConcreteProductB . vytvořit ; konec ; const Počet = 2 ; var Creators : array [ 1 .. Count ] of TCreator ; Produkt : TProdukt ; I : celé číslo ; begin // Pole tvůrců Creators [ 1 ] := TConcreteCreatorA . vytvořit ; Tvůrci [ 2 ] := TConcreteCreatorB . vytvořit ; // Iterujte přes tvůrce a vytvářejte produkty pro I := 1 to Count do begin Product := Creators [ I ] . Tovární metoda ; WriteLn ( Product . GetName ) ; produkt . zdarma ; konec ; for I := 1 to Count do Creators [ I ] . zdarma ; Readln ; konec . Příklad Delphi (virtuální konstruktory) program FactoryMethod ; {$APPTYPE KONZOLE} používá SysUtils ; typ // Produkt TProdukt = class ( TObject ) private SubName : string ; public function GetName : string ; virtuální ; abstraktní ; function GetFullName : string ; konstruktor Vytvořit ; virtuální ; abstraktní ; konec ; TProductClass = třída TProduct ; _ // ConcreteProductA TConcreteProductA = class ( TProduct ) public function GetName : string ; přepsat ; konstruktor Vytvořit ; přepsat ; konec ; // ConcreteProductB TConcreteProductB = class ( TProduct ) public function GetName : string ; přepsat ; konstruktor Vytvořit ; přepsat ; konec ; Funkce { TProdukt} TProdukt . GetFullName : string ; begin Vysledek := GetName + ' : ' + SubName ; konec ; { ConcreteProductA } konstruktor TConcreteProductA . vytvořit ; začít zděděný ; SubName := 'Podnázev produktu A' ; konec ; funkce TConcreteProductA . GetName : string ; begin Vysledek := 'ConcreteProductA' ; konec ; { ConcreteProductB } konstruktor TConcreteProductB . vytvořit ; začít zděděný ; SubName := 'Podnázev produktu B' ; konec ; funkce TConcreteProductB . GetName : string ; begin Vysledek := 'ConcreteProductB' ; konec ; const Počet = 2 ; var Creators : array [ 1 .. Count ] of TProductClass ; Produkt : TProdukt ; I : celé číslo ; begin // Pole tvůrců Creators [ 1 ] := TConcreteProductA ; Tvůrci [ 2 ] := TConcreteProductB ; // Iterujte přes tvůrce a vytvářejte produkty pro I := 1 to Count do begin Product := Creators [ I ] . vytvořit ; WriteLn ( Produkt . GetFullName ) ; produkt . zdarma ; konec ; Readln ; konec .

Action Script 3.0

Příklad v Action Script 3.0 protected class Creator { protected function factoryMethod () : Product { return null ; } public function someFunction () : void { var _product : Product = factoryMethod (); _produkt . doSome (); } } public class ConcreteCreatorA extends Creator { override protected function factoryMethod () : Product { return new ConcreteProductA (); } } public class ConcreteCreatorB extends Creator { override protected function factoryMethod () : Product { return new ConcreteProductB (); } } veřejné rozhraní Produkt { function doSome () : void {} } interní třída ConcreteProductA implementuje produkt { public function doSome () : void {} } interní třída ConcreteProductB implementuje produkt { public function doSome () : void {} } // IMPLEMENTACE public class Main { public function Main () { var _creatorA : ConcreteCreatorA = new ConcreteCreatorA (); _creatorA . someFunction (); var _creatorB : ConcreteCreatorB = new ConcreteCreatorB (); _creatorB . someFunction (); } }

scala

Příklad Scala abstraktní třída _ _ def getName : String } abstraktní třída _ _ def getProduct : AbstractProduct } class Beer rozšiřuje AbstractProduct { přepsat def getName : String = "Pivo" } class Wine rozšiřuje AbstractProduct { přepsat def getName : String = "Víno" } class BeerCreator rozšiřuje AbstractCreator { override def getProduct : AbstractProduct = new Beer } class WineCreator rozšiřuje AbstractCreator { override def getProduct : AbstractProduct = new Wine } objekt test { private def printProductName ( tvůrce : AbstractCreator ) : Unit = println ( tvůrce . getProduct . getName ) def main ( args : Array [ String ] ) : Unit = printProductName ( new BeerCreator ) printProductName ( new WineCreator ) }

Výsledek práce:
Vytvořeno: Víno Vytvořeno: Pivo

Ruby

Příklad v Ruby module FactoryMethod # Třída produktu 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 . nový konec konec # ConcreteCreatorA class ConcreteCreatorA < Creator def factoryMethod ConcreteProductA . nový konec konec # ConcreteCreatorB class ConcreteCreatorB < Creator def factoryMethod ConcreteProductB . nový konec konec konec # Klientský modul Klient obsahuje FactoryMethod tvůrci = [ ConcreteCreatorA . nový , ConcreteCreatorB . nový ] tvůrci . každý dělá | tvůrce | vloží " #{ creator . class } create Product: \t #{ creator . factoryMethod . productType } " end # => FactoryMethod::ConcreteCreatorA vytvořit Produkt: ConcreteProductA # => FactoryMethod::ConcreteCreatorB vytvořit Produkt: ConcreteProductB konec

Literatura

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Techniky objektově orientovaného navrhování. Design Patterns = Design Patterns : Prvky opakovaně použitelného objektově orientovaného softwaru. - Petrohrad. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (také ISBN 5-272-00355-1 )