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ž:
- třída předem neví, které objekty z kterých podtříd potřebuje vytvořit.
- třída je navržena tak, že objekty, které vytváří, jsou specifikovány podtřídami.
- třída deleguje své odpovědnosti na jednu z několika pomocných podtříd a plánuje se lokalizace znalostí o tom, která třída tyto odpovědnosti přebírá.
Struktura
- produkt - produkt
- definuje rozhraní pro objekty vytvořené abstraktní metodou;
- ConcreteProduct – konkrétní produkt
- implementuje rozhraní produktu ;
- tvůrce _
- deklaruje tovární metodu, která vrací objekt typu Product . Může také obsahovat "výchozí" implementaci této metody;
- může zavolat tovární metodu k vytvoření objektu typu Product ;
- ConcreteCreator - konkrétní tvůrce
- přepíše tovární metodu pro vytvoření a vrácení objektu třídy ConcreteProduct .
Výhody
- umožňuje učinit kód pro vytváření objektů univerzálnějším, nevázat se na konkrétní třídy (ConcreteProduct), ale operovat pouze se společným rozhraním (Product);
- umožňuje vytvořit vztah mezi paralelními hierarchiemi tříd.
Nevýhody
- nutnost vytvořit nástupce Creator pro každý nový typ produktu (ConcreteProduct).
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 )