A minta több különböző módon is implementálható, a konkrét programozási nyelvtől függően, mint például az egyke minta, az objektumorientált nyelvek osztályaiban a statikus tagok vagy a procedurális nyelvek globális függvényei. A Python nyelvben a modul minta egy beépített tulajdonság, minden .py kiterjesztésű fájl automatikusan egy-egy modul is.
Definíció és struktúra
A modul programtervezési minta a moduláris programozás paradigmája szerint definiált modul fogalmának megfelelő tulajdonságokat és szintaktikai struktúrát valósítja meg olyan programozási nyelveknél, amik nem rendelkeznek teljes (beépített) támogatással a modul koncepció megvalósítására.
Koncepció
A szoftverfejlesztésben, a forráskód komponensekbe szervezhető, amik egy adott funkcionalitást valósítanak meg, vagy tartalmaznak mindent ami egy adott (bővebb) feladat elvégzéséhez szükséges. A moduláris programozás ezen megközelítések egyike, ahol a modul egy ilyen forráskód komponensként fogható fel.
Sok elterjedt programozási nyelven, a „modul“ koncepciója nem teljes körűen támogatott beépített konstrukcióként.
Tulajdonságok
Ahhoz, hogy azt mondhassuk, hogy egy egyke osztály vagy bármilyen összetartozó kód-csoport implementálja ezt a mintát, a következő tulajdonságokkal kell rendelkeznie:
A kód egy részének globális vagy publikus elérésűnek kell lennie, és ennek megfelelően külső (globális/publikus) használatra tervezettnek. A további saját (private) vagy védett (protected) kódot a „fő“ (nyilvános) kód hívja (hajtja végre).
A modulnak kell hogy legyen egy inicializáló metódusa, amely megfeleltethető (hasonlít) egy osztály konstruktor metódusához. Ez a képesség általánosságban nincs meg a névtereknél (namespace).
A modulnak kell hogy legyen egy lezáró metódusa (finalizer), amely megfeleltethető (hasonlít) egy osztály destruktor metódusához. Ez a képesség sincs meg általában a névtereknél.
A modul egyes elemei is megkövetelhetnek további inicializációs/lezáró kódokat, amiket a modul inicializáló/lezáró metódusai hajtanak végre.
A legtöbb modul-elem valamilyen függvény, amelyek modulon kívüli elemeken hajtanak végre műveleteket, amely külső elemek függvény-argumentumként kerülnek átadásra. Az ilyen függvények általában „segédkódok“ (utility), „kódeszközök“ (tool) vagy „könyvtárak“ (library).
Implementációk
Az egyes programozási nyelvek szintaxisa és a szemantikája befolyásolja a minta implementációját.
Objektumorientált programozási nyelvek
Java
Habár a Java támogatja a névterek (namespace) fogalmát (ami a modul egy egyszerűsített változataként is felfogható), bizonyos esetekben előnyét élvezhetjük annak, ha a modul mintát használjuk, az egyszerű névterek helyett.
A következő példa az egyke mintát használja a modul minta megvalósítására.
Modul definíció
packageconsoles;importjava.io.InputStream;importjava.io.PrintStream;publicfinalclassMainModule{privatestaticMainModulesingleton=null;publicInputStreaminput=null;publicPrintStreamoutput=null;publicPrintStreamerror=null;publicMainModule(){// Szándékosan nem csinál semmit !!!}// ...publicstaticMainModulegetSingleton(){if(MainModule.singleton==null){MainModule.singleton=newMainModule();}returnMainModule.singleton;}// ...publicvoidprepare(){//System.out.println("consoles::prepare();");this.input=newInputStream();this.output=newPrintStream();this.error=newPrintStream();}publicvoidunprepare(){this.output=null;this.input=null;this.error=null;//System.out.println("consoles::unprepare();");}// ...publicvoidprintNewLine(){System.out.println();}publicvoidprintString(Stringvalue){System.out.print(value);}publicvoidprintInteger(intvalue){System.out.print(value);}publicvoidprintBoolean(booleanvalue){System.out.print(value);}publicvoidscanNewLine(){// to-do: ...}publicvoidscanString(Stringvalue){// to-do: ...}publicvoidscanInteger(intvalue){// to-do: ...}publicvoidscanBoolean(booleanvalue){// to-do: ...}// ...}
A JavaScript széleskörűen használt a WEB alapú technológiákban. Az objektumokat nem konstruktorok segítségével, hanem a prototípus klónozásával állítja elő.
Modul definíció
functionConsoleClass(){varInput=null;varOutput=null;varError=null;// ...this.prepare=function(){this.Input=newInputStream();this.Output=newOutputStream();this.Error=newErrorStream();}this.unprepare=function(){this.Input=null;this.Output=null;this.Error=null;}// ...varprintNewLine=function(){// code that prints a new line}varprintString=function(params){// code that prints parameters}varprintInteger=function(params){// code that prints parameters}varprintBoolean=function(params){// code that prints parameters}varScanNewLine=function(){// code that looks for a newline}varScanString=function(params){// code that inputs data into parameters}varScanInteger=function(params){// code that inputs data into parameters}varScanBoolean=function(params){// code that inputs data into parameters}// ...}
A modul minta, az objektumorientált nyelvek procedurális kiegészítéseként is tekinthető.
Habár a procedurális és moduláris programozási paradigmák gyakran használatosak együtt, vannak esetek, ahol egy procedurális programnyelv nem teljes mértékben támogatja a modulokat, ami miatt a modul minta implementálása szükséges.
PHP (procedurálisan)
Az alábbiakban egy a procedurális, névtér használat lehetősége előtti (5.3.0 verziót megelőző) PHP nyelvre alkalmazott példa. Ajánlott, hogy egy modul minden eleme (függvénye), el legyen látva egy a modul-fájl vagy a modul nevéhez kapcsolódó előtaggal, az esetleges azonosító ütközések elkerülése érdekében.
Modul definíció
<?php// filename: console.phpfunctionconsole_prepare(){// code that prepares a "console"}functionconsole_unprepare(){// code that unprepares a "console"}// ...functionconsole_printNewLine(){// code that ouputs a new line}functionconsole_printString(/* String */Value){// code that prints parameters}functionconsole_printInteger(/* Integer */Value){// code that prints parameters}functionconsole_printBoolean(/* Boolean */Value){// code that prints parameters}functionconsole_scanNewLine(){// code that looks for a new line}functionconsole_scanString(/* String */Value){// code that stores data into parameters}functionconsole_scanInteger(/* Integer */Value){// code that stores data into parameters}functionconsole_scanBoolean(/* Boolean */Value){// code that stores data into parameters}?>
Az alábbi példa a procedurális, névterek nélküli C nyelvre vonatkozik. Ajánlott, hogy egy modul minden eleme (függvénye), el legyen látva egy a modul-fájl vagy a modul nevéhez kapcsolódó előtaggal, az esetleges azonosító ütközések elkerülése érdekében.
Az alábbi példa a procedurális, nem moduláris Pascal nyelvre vonatkozik. Több Pascal dialektus támogatja a „unit“-oknak nevezett névterek használatát. Néhány dialektus a unitok inicializációs és lezáró (finalizer) kódjainak megadását is támogatja.
Ha a névterek használata nem támogatott, ajánlott, hogy egy modul minden eleme (függvénye), el legyen látva egy a modul-fájl vagy a modul nevéhez kapcsolódó előtaggal, az esetleges azonosító ütközések elkerülése érdekében.
Modul definíció
unitconsoles;(* filename: "consoles.pas" *)usescrt;procedureprepare();begin(* code that prepares console *)end;procedureunprepare();begin(* code that unprepares console *)end;// ...procedureprintNewLine();beginWriteLn();end;procedureprintString(Value:string);beginWrite(Value);end;procedureprintInteger(Value:integer);beginWrite(Value);end;procedureprintBoolean(Value:boolean);beginif(Value)thenbeginWrite('true');endelsebeginWrite('false');end;end;procedurescanNewLine();beginSeekEoLn();end;procedurescanString(Value:string);beginReadLn(Value);end;procedurescanInteger(Value:Integer);beginReadLn(Value);end;procedurescanBoolean(Value:Boolean);vartemp:string;beginReadLn(temp);if(Temp='true')thenbeginValue:=true;endelsebeginValue:=false;end;end;
Mind a névtér, mind a modul lehetővé teszi egymással összefüggő kód-entitások (pl. függvények) csoportosítását egyetlen azonosító „alá“ (modulnév / névtér), és bizonyos szituációkban felcserélhető módon használhatóak. A csoportosított entitások globálisan elérhetőek. Mindkét koncepció fő célja azonos.
Néhány esetben egy névtér megkövetelheti a részét képező globális elemek, egy metódus hívással történő inicializálását vagy lezárását.
Sok programozási nyelvben, a névterek közvetlenül nem támogatnak inicializációs vagy lezáró eljárásokat, és emiatt ezek nem tekinthetőek egyenlőnek a modul fogalmával. Ez a korlátozás oly módon oldható fel, hogy a globális függvényeket támogató névterekben, közvetlenül lekódolásra kerül egy inicializáló és egy lezáró (finalizer) függvény, amelyek direkt módon meghívásra kerülnek a főprogram kódjában.
Osztályok (classes) és a névterek
Az osztályok néha a névterekkel együtt, vagy azokat helyettesítve használatosak. Azokban a programozási nyelvekben (mint például a JavaScript) amik nem támogatják a névtereket, de támogatják az osztályokat és objektumokat, az osztálydefiníciók gyakran használatosak a névterek helyettesítésére. Az ilyen osztályokból rendszerint nem készülnek példányok és kizárólag statikus (osztályszintű) tag-metódusokból állnak, és az osztály neve használható névtérként (összefogva az osztály tag-metódusait).
Egyke (singleton) osztályok és a néveterek
Azokban az objektumorientált nyelvekben, ahol a névterek nem támogatottak, az egyke minta is használható a névterek helyettesítésére, a „nem példányosított osztály, statikus tag-metódusokkal“ megoldás helyett (lásd fentebb).
Kapcsolat más tervezési mintákkal
A modul minta implementálható az egyke minta specializált változataként. Más tervezési minták is alkalmazhatóak és kombinálhatóak, ugyanabban az osztályban. A modul minta használható, mint díszítő minta, vagy pehelysúlyú minta vagy akár illesztő mintaként.
A modul mint tervezési minta
A modul mintára tekinthetünk létrehozási mintaként és szerkezeti mintaként is. Egyrészt menedzseli más elemek létrehozását és szervezését, másrészt csoportba (struktúrába) foglalja az elemeket, ahogyan a szerkezeti minták teszik.
A minta alkalmazása támogatja azokat a specifikus eseteket, amikor egy osztályra, strukturált, procedurális kódként tekintünk, csakúgy, mint ennek a fordítottját, ahol strukturált, procedurális kódra tekintünk objektumorientáltan, egy osztály metódusaiként.
Fordítás
Ez a szócikk részben vagy egészben a Module pattern című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.