Objektovo orientované VBA: Návrhové vzory: jednoduchá továreň [Simple Factory]
Továreň je miesto, kde sa vyrábajú veci, a v objektovo orientovanom programovaní je továreň miesto, kde sa vyrábajú objekty – továrne zapuzdrujú vytváranie objektov. V továrni sa vytvorí inštancia triedy, nastaví sa jej stav a potom sa vráti volajúcemu. Jednoduchá továreň vo VBA môže vyzerať takto:
c
Public Function Factory(ByRef className As String) As Object
Select Case className
Case "Cat": Set Factory = New Cat
Case "Dog": Set Factory = New Dog
Case Else: Err.Raise Number:=..., Description:="Factory does not recognise thislassName."
End Select
End Function
Tu vidíme:
- Továreň je metóda, ktorá vracia hodnotu (tj funkciu);
- Používa hodnotu reťazca ‘názov triedy’ na určenie triedy, ktorá sa má vytvoriť;
- Hoci je vytvorený objekt typu ‚className‘, továreň ho vráti s typom ‚Object‘.
- Ak továreň nerozpozná className, vyhodí chybu.
Všimnite si, že hoci továreň vytvára objekt, ktorý zodpovedá „className“, vracia sa ako objekt typu „Object“. Keďže všetky objekty sú odvodené od „Objektu“, môžu byť ako také obsadené. Keďže funkcia VBA môže vrátiť iba jeden typ objektu a chceme, aby naša továreň mohla vytvárať objekty mnohých rôznych typov, volajúcemu vrátime „Objekt“. Volajúci potom môže pretypovať objekt tak, aby bol správneho typu (pretože to bol volajúci, ktorý požiadal o konkrétny typ).
Na ilustráciu tejto situácie Cast/Recast predpokladajme, že „Cat“ je definovaný ako:
Public Sub MakeNoise()
Debug.Print „Meow!“
End Sub
tj. trieda obsahuje len jednu verejnú metódu. Ak tento kód spustíte v štandardnom module:
Public Sub Test()
Dim o As Object, c As Cat
Set o = New Cat
o.MakeNoise
Set c = obj
c.MakeNoise
End Sub
Uvidíte, že bez ohľadu na to, či použijeme referenciu „o“ alebo referenciu „c“, volanie (volania) na MakeNoise prinesie rovnaký výsledok. V skutočnosti tu vidíte, že „Object“ a „Cat“ sú rozhrania triedy „Cat“. Výhodou továrne vracajúcej „Object“ je, že továreň môže byť použitá na vytvorenie inštancie a vrátenie akejkoľvek triedy, pretože všetky triedy zodpovedajú rozhraniu „Object“. V skutočnosti je lepšie povedať, že každý objekt, ktorý sa dá vytvoriť v továrni, musí zodpovedať danému rozhraniu. Vo vyššie uvedenom príklade bolo toto rozhranie „Objekt“ a keďže všetky triedy zodpovedajú „Objektu“, továreň mohla vrátiť inštanciu buď „Mačka“ alebo „Pes“.
Samozrejme, nie ste obmedzený len na „Objekt“. Môžete definovať svoje vlastné rozhranie, definovať triedy, ktoré implementujú toto rozhranie, a potom vytvoriť továreň, ktorá môže vytvárať iba inštancie objektov, ktoré vyhovujú tomuto rozhraniu. Keďže používate rozhrania, tento typ továrne sa nazýva „polymorfný“, pretože každý objekt vrátený volajúcemu bude mať rovnakú množinu polí, vlastností a metód (postupov a funkcií), ako ich definuje rozhranie. Volací kód teda môže tieto polia, vlastnosti a metódy využívať „agnosticky“, tzn. bez toho, aby poznal skutočný základný typ objektu, s ktorým pracuje. Polymorfizmus v práci.
Továreň na mačky/psy znázornená na samom začiatku tohto príspevku je príkladom jednoduchej továrne. „Jednoduché“ v tom zmysle, že zoznam možných objektov definuje vývojár v čase návrhu. Ak sa následne pridá nová trieda, potom je potrebné aktualizovať aj továrenský kód.
Vo VBA je možné vytvoriť komplexnejšiu továreň, ktorá skenuje kolekciu VBComponents za behu, aby zistila, ktoré triedy sú dostupné a aké rozhrania implementujú, a potom tieto údaje použije na vytvorenie skutočného kódu obsiahnutého v továrni (Opičia záplata v extrém). Schopnosť písať kód za behu je však bezpečnostným rizikom (takto sa šíria vírusy VBA) a vo väčšine podnikových prostredí je možnosť vývojára tak urobiť. Hoci to v žiadnom prípade nie je „najchladnejšie“ v spektre, Simple Factory znázornená vyššie je najjednoduchšie na pochopenie a implementáciu pre prvého OO vývojára VBA. Diskusiu o komplexnej továrni si uložím na ďalší blogový príspevok.
Zostáva len zvážiť, ako implementujete svoju Simple Factory. Ako je znázornené, „továreň“ je jednoducho funkcia. Preto môže byť umiestnený buď v štandardnom module alebo v module triedy. Vzhľadom na jeho dôležitosť ho zvyknem vkladať do vlastného modulu – buď štandardného modulu, alebo modulu statickej triedy (pozri môj predchádzajúci blog o statických triedach vo VBA). Samozrejme neexistujú žiadne pravidlá a je to úplne na osobných preferenciách – len si pamätajte, že čím je váš kód jednoduchší, tým ľahšie ho bude podporovať v budúcnosti.