Abstrakti tehdas (suunnittelukuvio)
Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 2. maaliskuuta 2018 tarkistetusta
versiosta . tarkastukset vaativat
25 muokkausta .
Abstrakti tehdas |
---|
abstrakti tehdas |
Tyyppi |
tuottaa |
Tarkoitus |
Tarjoaa käyttöliittymän toisiinsa liittyvien tai toisistaan riippuvaisten objektien perheiden luomiseen määrittelemättä niiden konkreettisia luokkia. |
Rakenne |
|
Pätee tapauksissa |
- Kun ohjelman on oltava riippumaton luotujen uusien objektien prosessista ja tyypeistä.
- Kun on tarpeen luoda toisiinsa liittyvien objektien perheitä tai ryhmiä, suljetaan pois mahdollisuus käyttää samanaikaisesti kohteita näistä eri joukoista samassa yhteydessä [1] .
|
Plussat |
- eristää tietyt luokat;
- yksinkertaistaa tuoteperheiden vaihtamista;
- takaa tuotteen yhteensopivuuden.
|
Miinukset |
- uudenlaiselle tuotteelle on vaikea lisätä tukea.
|
Kuvattu suunnittelukuvioissa |
Joo |
Abstrakti tehdas on generatiivinen suunnittelumalli, joka tarjoaa käyttöliittymän toisiinsa liittyvien tai toisiinsa liittyvien objektien perheiden luomiseen määrittelemättä niiden konkreettisia luokkia. Malli toteutetaan luomalla abstrakti luokka Factory, joka on käyttöliittymä järjestelmäkomponenttien luomiseen (esimerkiksi ikkunaliittymälle se voi luoda ikkunoita ja painikkeita). Sitten kirjoitetaan luokat , jotka toteuttavat tämän rajapinnan [2] .
Tapaaminen
Tarjoaa käyttöliittymän toisiinsa liittyvien tai toisistaan riippuvaisten objektien perheiden luomiseen määrittelemättä niiden konkreettisia luokkia.
Toteutus
Plussat
- eristää tietyt luokat;
- yksinkertaistaa tuoteperheiden vaihtamista;
- takaa tuotteen yhteensopivuuden.
Miinukset
- uudenlaiselle tuotteelle on vaikea lisätä tukea.
Sovellus
- Järjestelmän ei pitäisi olla riippuvainen siitä, miten siihen sisältyvät objektit luodaan, kootaan ja esitetään.
- Aiheeseen liittyviä objekteja kokoelmassa on käytettävä yhdessä, ja sinun on pakotettava tämä rajoitus voimaan.
- Järjestelmän on määritettävä jokin sen osaobjektien perheistä.
- On tarjottava objektikirjasto, joka paljastaa vain niiden rajapinnat, ei niiden toteutusta.
Esimerkkejä
Nopea esimerkki
Nopea lähdekoodi
//: Leikkikenttä - substantiivi: paikka, jossa ihmiset voivat leikkiä
/// <summary>
/// Tiivistelmä tehdasluokka
/// </summary>
protokolla AbstractFactory {
func createProductA () -> AbstractProductA
func createProductB () -> AbstractProductB
}
/// <summary>
/// Tehdasluokka #1
/// </summary>
class ConcreteFactory1 : AbstractFactory {
public func createProductA () -> AbstractProductA {
return ProductA1 ()
}
public func createProductB () -> AbstractProductB {
return ProductB1 ()
}
}
/// <summary>
/// Tehdasluokka #2
/// </summary>
class ConcreteFactory2 : AbstractFactory {
public func createProductA () -> AbstractProductA {
return ProductA2 ()
}
public func createProductB () -> AbstractProductB {
return ProductB2 ()
}
}
/// <summary>
/// Abstrakti tuoteluokka A
/// </summary>
protokolla AbstractProductA {}
//
/// <summary>
/// Abstrakti tuoteluokka B
/// </summary>
protokolla AbstractProductB {
func vuorovaikutuksessa ( a : AbstractProductA )
}
/// <summary>
/// Ensimmäinen tyypin A tuoteluokka
/// </summary>
luokka ProductA1 : AbstractProductA {}
/// <summary>
/// Tyypin B ensimmäinen tuoteluokka
/// </summary>
luokka TuoteB1 : AbstractProductB {
public func interact ( a : AbstractProductA ) {
print ( " \( type ( of : self )) interacts with \ ( tyyppi ( of : a . itse )) " )
}
}
/// <summary>
/// Tyypin A toinen tuoteluokka
/// </summary>
luokka ProductA2 : AbstractProductA {}
/// <summary>
/// Tyypin B toinen tuoteluokka
/// </summary>
luokka TuoteB2 : AbstractProductB {
public func interact ( a : AbstractProductA ) {
print ( " \( type ( of : self )) interacts with \ ( tyyppi ( of : a . itse )) " )
}
}
/// <summary>
/// Asiakasluokka, jossa objektien välinen vuorovaikutus tapahtuu
/// </summary>
class Client {
yksityinen anna _abstractProductA : AbstractProductA
private let _abstractProductB : AbstractProductB
// Rakentajan
julkinen aloitus ( tehdas : AbstractFactory ) { _abstractProductB = tehdas . luoTuoteB (); _abstractProductA = tehdas . luoTuoteA (); }
public func run () {
_abstractProductB . vuorovaikutuksessa ( a : _abstractProductA )
}
}
/// <summary>
/// Sovelluksen sisääntulopiste
/// </summary>
// Abstraktin tehdasnumeron kutsuminen
let factory1 = ConcreteFactory1 ()
let client1 = Asiakas ( tehdas : tehdas1 )
asiakas1 . juosta ()
// Kutsu abstrakti tehdas #2
let factory2 = ConcreteFactory2 ()
let client2 = Asiakas ( tehdas : tehdas2 )
asiakas2 . juosta ()
Esimerkki C# [3]
Lähdekoodi
C Sharpissa
käyttäen System ;
nimitila DoFactory.GangOfFour.Abstract.Structural
{
class MainApp
{
/// <summary>
/// Sovelluksen aloituspiste
/// </summary>
public static void Main ()
{
// Abstrakti tehdaskutsu #1
AbstractFactory factory1 = new ConcreteFactory1 ();
Asiakas asiakas1 = uusi asiakas ( tehdas1 );
asiakas1 . juosta ();
// Kutsu abstrakti tehdas #2
AbstractFactory factory2 = new ConcreteFactory2 ();
Asiakas asiakas2 = uusi asiakas ( tehdas2 );
asiakas2 . juosta ();
// Odotetaan syöttöä
Konsoli . ReadKey ();
}
}
/// <summary>
/// Abstract factory class
/// </summary>
abstrakti class AbstractFactory
{
public abstract AbstractProductA CreateProductA ();
julkinen abstrakti AbstractProductB CreateProductB ();
}
/// <summary>
/// Tehdasluokka #1
/// </summary>
class ConcreteFactory1 : AbstractFactory
{
public override AbstractProductA CreateProductA ()
{
return new ProductA1 ();
}
julkinen ohitus AbstractProductB CreateProductB ()
{
return new ProductB1 ();
}
}
/// <summary>
/// Tehdasluokka #2
/// </summary>
class ConcreteFactory2 : AbstractFactory
{
public override AbstractProductA CreateProductA ()
{
return new ProductA2 ();
}
public override AbstractProductB CreateProductB ()
{
return new ProductB2 ();
}
}
/// <summary>
/// Abstrakti tuoteluokka A
/// </summary>
abstrakti luokka AbstractProductA
{
}
/// <summary>
/// Abstrakti tuoteluokka B
/// </summary>
abstrakti luokka AbstractProductB
{
public abstract void Interact ( AbstractProductA a );
}
/// <summary>
/// Ensimmäinen tyypin A tuoteluokka
/// </summary>
luokka ProductA1 : AbstractProductA
{
}
/// <summary>
/// Ensimmäinen tyypin B tuoteluokka
/// </summary>
luokka TuoteB1 : AbstractProductB
{
public override void Interact ( AbstractProductA a )
{
Console . WriteLine ( tämä . GetType (). Nimi +
" on vuorovaikutuksessa " + a . GetType (). Nimi );
}
}
/// <summary>
/// Tyypin A toinen tuoteluokka
/// </summary>
luokka ProductA2 : AbstractProductA
{
}
/// <summary>
/// Tyypin B toinen tuoteluokka
/// </summary>
luokka TuoteB2 : AbstractProductB
{
public override void Interact ( AbstractProductA a )
{
Console . WriteLine ( tämä . GetType (). Nimi +
" on vuorovaikutuksessa " + a . GetType (). Nimi );
}
}
/// <summary>
/// Asiakasluokka, jossa objektien välinen vuorovaikutus tapahtuu
/// </summary>
class Client
{
private AbstractProductA _abstractProductA ;
yksityinen AbstractProductB _abstractProductB ;
// Constructor
public Client ( AbstractFactory factory )
{
_abstractProductB = tehdas . LuoTuoteB ();
_abstractProductA = tehdas . LuoTuoteA ();
}
public void Suorita ()
{
_abstractProductB . Interact ( _abstractProductA );
}
}
}
Java-esimerkki
Java lähde
public class AbstractFactoryExample {
public static void main ( String [ ] args ) {
AbstractFactory tehdas1 = uusi ConcreteFactory1 ();
Asiakas asiakas1 = uusi asiakas ( tehdas1 );
asiakas1 . suorittaa ();
AbstractFactory factory2 = uusi ConcreteFactory2 ();
Asiakas asiakas2 = uusi asiakas ( tehdas2 );
asiakas2 . suorittaa ();
}
}
class Client {
yksityinen AbstractProductA productA ;
yksityinen AbstraktiTuoteB tuoteB ;
Asiakas ( AbstractFactory tehdas ) {
productA = tehdas . luoTuoteA ();
tuoteB = tehdas . luoTuoteB ();
}
void execute () {
tuoteB . olla vuorovaikutuksessa ( tuoteA );
}
}
käyttöliittymä AbstractFactory {
AbstractProductA createProductA ();
AbstractProductB createProductB ();
}
käyttöliittymä AbstractProductA {
void interact ( AbstractProductB b );
}
käyttöliittymä AbstractProductB {
void interact ( AbstractProductA a );
}
luokka ConcreteFactory1 toteuttaa AbstractFactory {
@Override
public AbstractProductA createProductA () {
return new ProductA1 ();
}
@Ohita
julkinen AbstractProductB createProductB () {
return new ProductB1 ();
}
}
luokka ConcreteFactory2 toteuttaa AbstractFactory {
@Override
public AbstractProductA createProductA () {
return new ProductA2 ();
}
@Override
public AbstractProductB createProductB () {
return new ProductB2 ();
}
}
luokan TuoteA1 toteuttaa AbstractProductA {
@Override
public void interact ( AbstractProductB b ) {
System . ulos . println ( tämä . getClass (). getName () + " vuorovaikutuksessa " + b . getClass (). getName ());
}
}
luokan tuoteB1 toteuttaa AbstractProductB {
@Override
public void interact ( AbstractProductA a ) {
Järjestelmä . ulos . println ( tämä . getClass (). getName () + " vuorovaikutuksessa " + a . getClass (). getName ());
}
}
luokan TuoteA2 toteuttaa AbstractProductA {
@Override
public void interact ( AbstractProductB b ) {
System . ulos . println ( tämä . getClass (). getName () + " vuorovaikutuksessa " + b . getClass (). getName ());
}
}
luokan tuoteB2 toteuttaa AbstractProductB {
@Override
public void interact ( AbstractProductA a ) {
Järjestelmä . ulos . println ( tämä . getClass (). getName () + " vuorovaikutuksessa " + a . getClass (). getName ());
}
}
PHP5 esimerkki
PHP5 lähdekoodi
käyttöliittymä IHead
{
julkinen funktio piirtopää ( $x , $y );
}
class RedHead toteuttaa IHead
{
public function drawHead ( $x , $y ) {
echo 'Punainen pää akselilla x =' . $x . ' ja akseli y = ' . $y . '</br>' . PHP_EOL ;
}
}
class WhiteHead toteuttaa IHead
{
julkinen funktio piirtopää ( $x , $y ) {
echo 'Valkoinen pääsi akselilla x =' . $x . ' ja akseli y = ' . $y . '</br>' . PHP_EOL ;
}
}
käyttöliittymä IBody
{
julkinen toiminto drawBody ( $x , $y );
}
class RedBody toteuttaa IBody
{
public function drawBody ( $x , $y ) {
echo 'Punainen kehosi akselilla x =' . $x . ' ja akseli y = ' . $y . '</br>' . PHP_EOL ;
}
}
class WhiteBody toteuttaa IBody
{
julkinen toiminto drawBody ( $x , $y ) {
echo 'Valkoinen kehosi akselilla x =' . $x . ' ja akseli y = ' . $y . '</br>' . PHP_EOL ;
}
}
/**
* Käyttöliittymä ISnowman - tämä on abstrakti tehdas
*/
käyttöliittymä ISnowman
{
julkinen funktio piirrospää ( $x , $y );
julkinen funktio drawBody ( $x , $y );
}
/**
* Luokka WhiteSnowman - betonitehdas
*/
luokka WhiteSnowman työstää ISnowman { suojattu $ pää ; suojattu $body ;
public function __construct () {
$this -> head = new WhiteHead ();
$this -> body = uusi WhiteBody ();
}
julkinen funktio piirtopää ( $x , $y ) {
$this -> head -> drawHead ( $x , $y );
}
julkinen funktio drawBody ( $x , $y ) {
$this -> body -> drawBody ( $x , $y );
}
}
/**
* Luokka RedSnowman - betonitehdas
*/
luokka RedSnowman toteuttaa ISnowman
{
suojattu $pää ;
suojattu $body ;
julkinen funktio __construct () {
$this -> head = new RedHead ();
$this -> body = uusi RedBody ();
}
julkinen funktio piirtopää ( $x , $y ) {
$this -> head -> drawHead ( $x , $y );
}
julkinen funktio drawBody ( $x , $y ) {
$this -> body -> drawBody ( $x , $y );
}
}
funktio lumiukko ( ISnowman $lumiukko ) {
$lumiukko -> piirtopää ( 1 , 1 );
$lumiukko -> drawBody ( 1 , 2 );
}
$typeSnowman = 'punainen' ;
// valitsemme perhetyypin koodin alussa
if ( $typeSnowman == 'red' )
$lumiukko = new RedLumiukko ();
else
$lumiukko = uusi WhiteLumiukko ();
lumiukko ( $lumiukko );
Python-esimerkki
Lähdekoodi
Pythonissa
abc importista ABCMeta , abstrakti menetelmä
luokka Olut ( metaluokka = ABCMeta ):
pass
luokan välipala ( metaluokka = ABCMeta ):
@abstractmethod
def interact ( itse , olut : Olut ) -> Ei mitään :
pass
class AbstractShop ( metaluokka = ABCMeta ):
@abstractmethod
def buy_beer ( self ) -> Beer :
pass
@abstractmethod
def buy_snack ( itse ) -> Välipala :
pass
luokka Tuborg ( Olut ):
pass
luokka Staropramen ( Olut ):
pass
luokan maapähkinät ( välipala ):
def interact ( itse , olut : Olut ) -> Ei mitään :
print ( 'Joimme pullon olutta {} ja söimme sen maapähkinöiden kanssa' . muodossa (
olut . __class__ . __name__ ))
luokan sirut ( välipala ):
def interact ( self , olut : Beer ) -> None :
print ( 'Joimme muutaman oluen {} ja söimme pussin chipsejä' . muodossa (
olut . __class__ . __name__ ))
luokka ExpensiveShop ( AbstractShop ):
def buy_beer ( itse ) -> Olut :
paluu Tuborg ( )
def buy_snack ( itse ) -> Välipala :
paluu Maapähkinät ( )
luokan CheapShop ( AbstractShop ):
def buy_beer ( itse ) -> Olut :
paluu Staropramen ( )
def buy_snack ( itse ) -> Välipala :
palauta pelimerkit ()
if __name__ == '__main__' :
kallis_kauppa = KallisShop ( )
cheap_shop = HalpaShop ()
print ( 'OUTPUT:' )
olut = kallis_kauppa . osta_olutta ()
välipala = halpa_kauppa . buy_snack ()
välipala . vuorovaikutuksessa ( olut )
olut = halpa_kauppa . osta_olutta ()
välipala = kallis_kauppa . buy_snack ()
välipala . olla vuorovaikutuksessa ( olut )
'''
TULOS:
Joimme muutaman tölkin Tuborgin olutta ja söimme pussin sipsejä
Joimme pullon Staropramen-olutta ja puresimme sitä maapähkinöillä
'''
Scala esimerkki
Scala lähdekoodi
abstrakti luokka AbstractTerrestrialAnimal {
def walk : merkkijono
}
abstrakti luokka _ _
def swim : String
_
abstrakti luokka _ _
def getCity : merkkijono
def getTerrestrialAnimal : AbstractTerrestrialAnimal
def getWaterAnimal : AbstractWaterAnimal
}
luokka Wolverine extends AbstractTerrestrialAnimal {
ohita def walk : String = "Ahma kävelee"
}
class HoneyBadger extends AbstractTerrestrialAnimal {
ohita def walk : String = "Kunamäyrä kävelee"
}
luokka Walrus laajentaa AbstractWaterAnimal {
ohittaa def swim : String = "Mursu ui"
}
class SeaLion laajentaa AbstractWaterAnimal {
override def swim : String = "Merileijona ui"
}
class MunichZoo laajentaa AbstractZoo {
ohita def getCity : String = "München"
ohita def getTerrestrialAnimal : AbstractTerrestrialAnimal = uusi Wolverine
ohita def getWaterAnimal : AbstractWaterAnimal = uusi mursu
}
class CapeTownZoo laajentaa AbstractZoo {
ohita def getCity : String = "Kapkaupunki"
ohita def getTerrestrialAnimal : AbstractTerrestrialAnimal = uusi HoneyBadger
ohita def getWaterAnimal : AbstractWaterAnimal = uusi SeaLion
}
object AbstractFactoryTest {
yksityinen def testZoo ( eläintarha : AbstractZoo ): Yksikkö = {
println ( s"Zoo of ${ zoo . getCity } :" )
println ( eläintarha . getTerrestrialAnimal . walk )
println ( eläintarha . getWaterAnimal . uida )
}
def main ( args : Array [ String ]) Unit = {
testZoo ( new CapeTownZoo )
testZoo ( new MunichZoo )
}
}
Siirry esimerkkiin
Lähdekoodi
Gossa
paketin pääasiallinen
tuo "fmt"
kirjoita Unit interface {
Mikä () merkkijono
}
kirjoita Action interface {
Mikä () merkkijono
}
kirjoita Aseta käyttöliittymä {
Mikä () merkkijono
}
tyyppi TransportFactory - liitäntä {
MakeUnit () Unit
MakeAction () Action
MakePlace () Paikka
}
tyyppi auton rakenne {}
func ( itse auto ) Mikä () merkkijono {
return "auto"
}
kirjoita Ride struct {}
func ( self Ride ) Mikä () merkkijono {
return "ride"
}
tyyppi tierakenne { }
func ( itse tie ) Mikä () merkkijono {
return "tie"
}
tyyppi LandTransportFactory struct {}
func ( itse LandTransportFactory ) Merkkiyksikkö ( ) Yksikkö {
paluu & auto {}
}
Func ( itse LandTransportFactory ) MakeAction ( ) Action { return & Ride {} }
Func ( itse LandTransportFactory ) MakePlace ( ) Paikka { paluu & tie {} }
tyyppi Venerakenne { }
func ( itse Vene ) Mikä () merkkijono {
return "boat"
}
tyyppi Purjerakenne { }
func ( self Sail ) Mikä () merkkijono {
return "purje"
}
tyyppi Sea struct {}
func ( itse Meri ) Mikä () merkkijono {
return "meri"
}
tyyppi SeaTransportFactory struct {}
func ( itse SeaTransportFactory ) MakeUnit ( ) Yksikkö {
paluu & vene {}
}
Func ( itse SeaTransportFactory ) MakeAction ( ) Action { paluu & purjehtii {} }
Func ( itse SeaTransportFactory ) MakePlace ( ) Paikka { paluu & meri {} }
func action ( tehdas TransportFactory ) {
yksikkö := tehdas . MakeUnit ()
unit_action := tehdas . MakeAction ()
paikka := tehdas . MakePlace ()
fmt . Printf ( "%s %ss %s:n päällä.\n" ,
yksikkö . Mikä (), yksikkötoiminto . Mikä (), paikka . Mikä ())
}
func main () {
action ( & LandTransportFactory {})
action ( & SeaTransportFactory {})
}
Johtopäätös
Auto ajaa tien yli.
Vene purjehtii meren yli.
Rubiiniesimerkki
Rubyn lähdekoodi
moduuli AbstractFactoryPattern
# Tarjoa käyttöliittymä toisiinsa liittyvien tai objektien perheiden luomiseen ilman niiden konkreettisia luokkia
# Abstract Factory
-luokka WarriorFactory
def create_knight
raise NotImplementedError
end
def create_archer
raise NotImplementedError
end
end
#
Betonitehdasluokka OrcWarriorFactory < WarriorFactory def create_knight OrcKnight . uusi loppu
def create_archer
OrcArcher . uusi
loppu
loppu
#
Betonitehdasluokka ElfWarriorFactory < WarriorFactory def create_knight ElfKnight . uusi loppu
def create_archer
ElfArcher . uusi
loppu
loppu
# Abstrakti
Tuoteluokka Knight
def tarkastaa
itsensä . luokkaa . nimi . split ( '::' ) . viimeinen
loppu
loppu
# Abstrakti
Tuoteluokka Archer def tarkastaa itsensä . luokkaa . nimi . split ( '::' ) . viimeinen loppu loppu
#
Tuoteluokka OrcKnight < Knight end
#
Tuoteluokka ElfKnight < Knight end
#
Tuoteluokka OrcArcher < Archer end
#
Tuoteluokka ElfArcher < Archer end
# Asiakasluokka
Army def alustus ( tehdas ) @knights = [ ] 3 . kertaa { @knights << tehdas . luo_ritari }
@archers = []
3 . kertaa { @archers << tehdas . create_archer }
loppu
def inspect
"Knights #{ @knights . map ( & :inspect ) } Archers #{ @archers . map ( & :inspect ) } "
end
end
itsevarmasti . _ juokse örkkejä = armeija . new ( OrcWarriorFactory . new ) laittaa "Orcs army: #{ orcs . inspect } "
tontut = armeija . uusi ( ElfWarriorFactory . new )
laittaa "Tontut armeija: #{ elves . inspect } "
end
end
AbstractFactoryPattern . juosta
# Orkkiarmeija: Knights ["OrcKnight", "OrcKnight", "OrcKnight"] Jousimiehet ["OrcArcher", "OrcArcher", "OrcArcher"]
# Haltiaarmeija: Knights ["ElfKnight", "ElfKnight", "ElfKnight"] Jousimiehet ["ElfArcher", "ElfArcher", "ElfArcher"]
Kirjallisuus
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Olio-suunnittelun tekniikat. Suunnittelumallit = Suunnittelumallit: Uudelleenkäytettävän olio-ohjelmiston elementit. - Pietari. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (myös ISBN 5-272-00355-1 )
Linkit
Muistiinpanot
- ↑ Abstrakti tehdaskuvio . Haettu 14. kesäkuuta 2013. Arkistoitu alkuperäisestä 14. kesäkuuta 2013. (määrätön)
- ↑ Kuvioiden luominen: Abstrakti tehdas . Haettu 14. kesäkuuta 2013. Arkistoitu alkuperäisestä 14. kesäkuuta 2013. (määrätön)
- ↑ Abstract Factory .NET Design Pattern C#:ssa ja VB:ssä - dofactory.com . www.dofactory.com Käyttöpäivä: 3. maaliskuuta 2016. Arkistoitu alkuperäisestä 3. maaliskuuta 2016. (määrätön)