Abstrakti tehtaan kuvio - Abstract factory pattern

Image
UML-luokkakaavio

Abstrakti tehtaan malli tarjoaa tavan kapseloida ryhmän yksittäisiä tehtaita , joilla on yhteinen teema täsmentämättä niiden konkreettisia luokkia. Normaalikäytössä asiakasohjelmisto luo abstraktin tehtaan konkreettisen toteutuksen ja käyttää sitten tehtaan yleistä käyttöliittymää teemaan kuuluvien konkreettisten objektien luomiseen . Asiakas ei tiedä (tai hoidon), mitä konkreettisia esineitä se saa kaikista näistä sisäisten tehtaita, koska se käyttää ainoastaan yleisiä rajapinnat niiden tuotteita. Tämä malli erottaa objektijoukon toteutuksen yksityiskohdat niiden yleisestä käytöstä ja perustuu objektien kokoonpanoon, koska objektin luonti toteutetaan tehdasrajapinnassa paljastetuissa menetelmissä.

Esimerkki tästä olisi abstrakti tehdasluokka, DocumentCreatorjoka tarjoaa käyttöliittymät useiden tuotteiden (esim. createLetter()Ja createResume()) luomiseen . Järjestelmällä olisi mikä tahansa määrä johdettuja konkreettisia versioita DocumentCreatorluokan kaltaisesta FancyDocumentCreatortai ModernDocumentCreator, joista jokaisella on erilainen toteutus, createLetter()ja createResume()joka luo vastaavan objektin, kuten FancyLettertai ModernResume. Jokainen näistä tuotteista on johdettu yksinkertaisesta abstraktista luokasta, jonka kaltainen Lettertai Resumejosta asiakas on tietoinen. Asiakas koodi saisi asianmukaista oikeusasteen n DocumentCreatorja soittaa sen tehtaan menetelmiä . Jokainen tuloksena olevista objekteista luotiin samasta DocumentCreatortoteutuksesta ja niillä olisi yhteinen teema (ne kaikki olisivat hienoja tai moderneja esineitä). Asiakkaan on vain osattava käsitellä abstrakti Lettertai Resumeluokka, ei tarkkaa versiota, jonka se sai betonitehtaalta.

Tehdas on betoniluokan sijainti koodissa, johon objektit rakennetaan . Mallin käyttämisen tarkoituksena on eristää esineiden luominen niiden käytöstä ja luoda samankaltaisten esineiden perheitä tarvitsematta olla riippuvainen niiden konkreettisista luokista. Tämä mahdollistaa uusien johdettujen tyyppejä otetaan käyttöön ilman muutoksia koodi käyttää perustaa luokan .

Tämän mallin avulla on mahdollista vaihtaa konkreettisia toteutuksia muuttamatta niitä käyttävää koodia edes ajon aikana . Tämän mallin käyttö, kuten samankaltaisissa suunnittelumalleissa , voi kuitenkin johtaa tarpeettomaan monimutkaisuuteen ja ylimääräiseen työhön koodin alkuperäisessä kirjoittamisessa. Lisäksi korkeampi erottelu ja abstraktio voivat johtaa järjestelmiin, joita on vaikeampaa virheenkorjauksessa ja ylläpidossa.

Yleiskatsaus

Abstraktin tehtaan suunnittelumalli on yksi kahdestakymmenestä kolmesta tunnetusta GoF-suunnittelumallista, jotka kuvaavat toistuvien suunnitteluongelmien ratkaisemista joustavien ja uudelleenkäytettävien olio-ohjelmistojen suunnittelulle, toisin sanoen kohteille, jotka on helpompi toteuttaa, muuttaa, testata, ja käyttää uudelleen.

Abstraktin tehtaan suunnittelumalli ratkaisee esimerkiksi:

  • Kuinka sovellus voi olla riippumaton siitä, miten sen objektit luodaan?
  • Kuinka luokka voi olla riippumaton siitä, miten sen tarvitsemat objektit luodaan?
  • Kuinka sukulaisia ​​tai riippuvaisia ​​esineitä voidaan luoda?

Objektien luominen suoraan luokan sisällä, joka vaatii objekteja, on joustamatonta, koska se sitouttaa luokan tiettyihin kohteisiin ja tekee mahdottomaksi muuttaa instanssia myöhemmin itsenäisesti luokasta (ilman, että sitä tarvitsee muuttaa). Se estää luokan uudelleenkäytön, jos muita esineitä tarvitaan, ja se vaikeuttaa luokan testaamista, koska todellisia esineitä ei voida korvata pilkko-objekteilla.

Abstraktin tehtaan suunnittelumalli kuvaa kuinka ratkaista tällaiset ongelmat:

  • Kapseloi objektin luominen erilliseen (tehdas) objektiin. Eli määritä käyttöliittymä (AbstractFactory) objektien luomista varten ja toteuta käyttöliittymä.
  • Luokka delegoi objektin luomisen tehdasobjektille sen sijaan, että luodaan objekteja suoraan.

Tämä tekee luokan riippumaton siitä, miten sen objektit luodaan (mitkä konkreettiset luokat ovat ilmentyneitä). Luokka voidaan määrittää tehdasobjektilla, jota se käyttää objektien luomiseen, ja vielä enemmän, tehdasobjekti voidaan vaihtaa ajon aikana.

Määritelmä

Abstraktin tehdasmallin ydin on "tarjota käyttöliittymä toisiinsa liittyvien tai riippuvaisten objektien perheiden luomiseksi määrittelemättä niiden konkreettisia luokkia".

Käyttö

Tehdas määrittää todellisen konkreettinen tyypin objekti on luotu, ja se on tässä, että objekti on todella luodaan (Java, esimerkiksi, että uusi operaattori ). Tehdas palauttaa kuitenkin vain abstraktin osoittimen luotuun konkreettiseen esineeseen .

Tämä eristää asiakaskoodin objektin luomisesta pyytämällä asiakkaita pyytämään tehdasobjektia luomaan halutun abstraktityypin objektin ja palauttamaan abstraktin osoittimen objektille.

Koska tehdas palauttaa vain abstraktin osoittimen, asiakaskoodi (joka pyysi objektia tehtaalta) ei tiedä juuri luodun objektin todellista konkreettista tyyppiä eikä sitä rasita. Abstrakti tehdas tietää kuitenkin konkreettisen esineen tyypin (ja siten betonitehtaan); esimerkiksi tehdas voi lukea sen kokoonpanotiedostosta. Asiakkaan ei tarvitse määrittää tyyppiä, koska se on jo määritetty määritystiedostossa. Tämä tarkoittaa erityisesti:

  • Asiakas koodi eivät tunne lainkaan betonin tyyppiä , ei tarvitse sisällyttää mitään otsikkotiedostot tai luokan ilmoitusten liittyvät siihen. Asiakaskoodi käsittelee vain abstraktityyppiä. Konkreettisia objekteja luodaan tehtaalla, mutta asiakaskoodi käyttää tällaisia ​​objekteja vain niiden abstraktin käyttöliittymän kautta .
  • Uusien betonityyppien lisääminen tapahtuu muokkaamalla asiakaskoodia käyttämään eri tehtaita, joka on tyypillisesti yksi rivi yhdessä tiedostossa. Tehtaan eri luo sitten esineitä on eri konkreettien, mutta silti palauttaa osoittimen on saman abstraktin tyyppiä kuin ennen - näin eristävä asiakkaan koodin muutoksesta. Tämä on huomattavasti helpompaa kuin asiakaskoodin muokkaaminen uuden tyypin luomiseksi, mikä vaatii jokaisen sijainnin vaihtamisen koodissa, johon uusi objekti luodaan (samoin kuin varmistamalla, että kaikilla tällaisilla koodipaikoilla on myös tietoa uudesta betonityypistä, sisällyttämällä esimerkiksi konkreettisen luokan otsikkotiedoston). Jos kaikki tehdasobjektit on tallennettu globaalisti singleton- objektiin ja kaikki asiakaskoodit kulkevat singletonin läpi päästäksesi oikeaan tehtaaseen objektin luomista varten, tehtaiden vaihtaminen on yhtä helppoa kuin singleton-objektin vaihtaminen.

Rakenne

UML-kaavio

Luokkakaavioesimerkki GUIFactory-käyttöliittymän metodi createButton palauttaa Button-tyyppiset objektit.  Mikä painikkeen toteutus palautetaan, riippuu siitä, mikä GUIFactory-toteutus käsittelee menetelmän kutsua.
Luokkakaavio esimerkiksi menetelmä createButtonon GUIFactoryrajapinta palauttaa esineet tyypin Button. Palautuksen toteutus Buttonriippuu siitä, mikä toteutus GUIFactorykäsittelee menetelmäkutsu.
Esimerkki UML-luokan ja sekvenssikaaviosta Abstract Factory -suunnittelukuvioon.  [8]
Esimerkki UML-luokan ja sekvenssikaaviosta Abstract Factory -suunnittelukuvioon.

Edellä UML luokkakaavio , Clientluokka, joka vaatii ProductAja ProductBesineet ei instanssia ProductA1ja ProductB1luokat suoraan. Sen sijaan Clientviittaa AbstractFactorykäyttöliittymään objektien luomiseksi, mikä tekee Clientriippumaton siitä, miten objektit luodaan (mitkä konkreettiset luokat ovat instantioituja). Factory1Luokka toteuttaa AbstractFactoryrajapinnan käynnistämästä ProductA1ja ProductB1luokat. UML kaavio esittää ajonaikaisen yhteisvaikutukset: esine puhelut on esine, joka luo ja palauttaa objektin. Tämän jälkeen puhelut päälle , joka luo ja palauttaa objektin.
ClientcreateProductA()Factory1ProductA1ClientcreateProductB()Factory1ProductB1

LePUS3-kaavio

Python- esimerkki

from abc import ABC, abstractmethod
from sys import platform


class Button(ABC):
    @abstractmethod
    def paint(self):
        pass


class LinuxButton(Button):
    def paint(self):
        return "Render a button in a Linux style"


class WindowsButton(Button):
    def paint(self):
        return "Render a button in a Windows style"


class MacOSButton(Button):
    def paint(self):
        return "Render a button in a MacOS style"


class GUIFactory(ABC):
    @abstractmethod
    def create_button(self):
        pass


class LinuxFactory(GUIFactory):
    def create_button(self):
        return LinuxButton()


class WindowsFactory(GUIFactory):
    def create_button(self):
        return WindowsButton()


class MacOSFactory(GUIFactory):
    def create_button(self):
        return MacOSButton()


if platform == "linux":
    factory = LinuxFactory()
elif platform == "darwin":
    factory = MacOSFactory()
elif platform == "win32":
    factory = WindowsFactory()
else:
    raise NotImplementedError(f"Not implemented for your platform: {platform}")

button = factory.create_button()
result = button.paint()
print(result)

Vaihtoehtoinen toteutus käyttämällä luokkia itse tehtaina:

from abc import ABC, abstractmethod
from sys import platform


class Button(ABC):
    @abstractmethod
    def paint(self):
        pass


class LinuxButton(Button):
    def paint(self):
        return "Render a button in a Linux style"


class WindowsButton(Button):
    def paint(self):
        return "Render a button in a Windows style"


class MacOSButton(Button):
    def paint(self):
        return "Render a button in a MacOS style"


if platform == "linux":
    factory = LinuxButton
elif platform == "darwin":
    factory = MacOSButton
elif platform == "win32":
    factory = WindowsButton
else:
    raise NotImplementedError(f"Not implemented for your platform: {platform}")

button = factory()
result = button.paint()
print(result)

Katso myös

Viitteet

Ulkoiset linkit