„Szerkesztő:PolyakLaci/próbalap” változatai közötti eltérés

Tartalom törölve Tartalom hozzáadva
PolyakLaci (vitalap | szerkesztései)
PolyakLaci (vitalap | szerkesztései)
Eltávolította a lap teljes tartalmát
 
1. sor:
A [[szoftverfejlesztés]]ben a ''modul minta'' egy olyan [[programtervezési minta]], amit a [[moduláris programozás]]ban definiált ''[[szoftver modul]]ok'' létrehozására használnak egy olyan [[programozási nyelv]]en, ami nem rendelkezik teljes (beépített) támogatással a modul koncepció megvalósítására.
 
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 programtervezési minta|egyke minta]], az objektumorientált nyelvek [[osztály|osztályaiban]] a [[statikus tag|statikus tagok]] és a procedurális nyelvek globális függvényei. A [[Python (programozási nyelv)|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.
 
[[File:Module-software-design-pattern.png|center|thumb|640px|alt=Egy objektum modul minta [[UML]] ábrája.|Egy objektum modul minta [[UML]] ábrája.]]
 
== 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.
 
== 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évtér|névtereknél]] ([[:en:namespace|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 (programozási nyelv)|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 programtervezési minta|egyke mintát]] használja a modul minta megvalósítására.
 
===== Modul definíció =====
 
<source lang="java">
package consoles;
 
import java.io.InputStream;
import java.io.PrintStream;
 
public final class MainModule {
 
private static MainModule singleton = null;
 
public InputStream input = null;
public PrintStream output = null;
public PrintStream error = null;
 
public MainModule() {
// Szándékosan nem csinál semmit !!!
}
 
// ...
 
public static MainModule getSingleton() {
if (MainModule.singleton == null) {
MainModule.singleton = new MainModule();
}
return MainModule.singleton;
}
 
// ...
 
public void prepare() {
//System.out.println("consoles::prepare();");
 
this.input = new InputStream();
this.output = new PrintStream();
this.error = new PrintStream();
}
public void unprepare() {
this.output = null;
this.input = null;
this.error = null;
//System.out.println("consoles::unprepare();");
}
// ...
public void printNewLine() {
System.out.println();
}
 
public void printString(String value) {
System.out.print(value);
}
 
public void printInteger(int value) {
System.out.print(value);
}
 
public void printBoolean(boolean value) {
System.out.print(value);
}
public void scanNewLine() {
// to-do: ...
}
public void scanString(String value) {
// to-do: ...
}
 
public void scanInteger(int value) {
// to-do: ...
}
 
public void scanBoolean(boolean value) {
// to-do: ...
}
// ...
}
</source>
 
===== Használat =====
 
<source lang="java">
import consoles;
 
class ConsoleDemo {
public static MainModule console = null;
 
public static void prepare() {
console = MainModule.getSingleton();
 
console.prepare();
}
 
public static void unprepare() {
console.unprepare();
}
 
public static void execute(String[] args) {
console.printString("Hello World");
console.printNewLine();
console.scanNewLine();
}
 
public static void main(String[] args) {
prepare();
execute(args);
unprepare();
}
}
</source>
 
==== C# (C Sharp .Net) ====
 
A [[C Sharp|C#]], csakúgy mint a Java, támogatja a névterek használatát, de adott esetben a modul minta alkalmazása továbbra is hasznos lehet.
 
A következő példa az [[Egyke programtervezési minta|egyke mintát]] használja a modul minta megvalósítására.
 
===== Modul definíció =====
 
<source lang="csharp">
using System;
using System.IO;
using System.Text;
 
namespace Consoles {
 
public sealed class MainModule {
private static MainModule Singleton = null;
public InputStream input = null;
public OutputStream output = null;
public ErrorStream error = null;
 
// ...
 
public MainModule () {
// Szándékosan nem csinál semmit !!!
}
 
// ...
 
public MainModule getSingleton() {
if (MainModule.Singleton == null)
{
MainModule.Singleton = new MainModule();
}
 
return MainModule.Singleton;
}
 
// ...
 
public void prepare() {
//System.WriteLine("console::prepare();");
 
this.input = new InputStream();
this.output = new OutputStream();
this.error = new ErrorStream();
}
public void unprepare() {
this.output = null;
this.input = null;
this.error = null;
//System.WriteLine("console::unprepare();");
}
// ...
public void printNewLine() {
System.Console.WriteLine("");
}
public void printString(String Value) {
System.Console.Write(Value);
}
public void printInteger(Integer Value) {
System.Console.Write(Value);
}
public void printBoolean(Boolean Value) {
System.Console.Write(Value);
}
public void ScanNewLine() {
// to-do: ...
}
public void ScanString(String Value) {
// to-do: ...
}
public void ScanInteger(Integer Value) {
// to-do: ...
}
public void ScanBoolean(Boolean Value) {
// to-do: ...
}
// ...
}
}
</source>
 
===== Használat =====
 
<source lang="csharp">
class ConsoleDemo {
public static Consoles.MainModule Console = null;
public static void prepare()
{
Console = Consoles.MainModule.getSingleton();
Console.prepare();
}
public static void unprepare()
{
Console.unprepare();
}
public static void execute()
{
Console.PrintString("Hello World");
Console.PrintNewLine();
Console.ScanNewLine();
}
public static void main()
{
prepare();
execute(args);
unprepare();
}
}
</source>
 
=== Prototípus alapú programozási nyelvek ===
 
==== JavaScript ====
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ó =====
 
<source lang="javascript">
function ConsoleClass() {
var Input = null;
var Output = null;
var Error = null;
 
// ...
this.prepare = function() {
this.Input = new InputStream();
this.Output = new OutputStream();
this.Error = new ErrorStream();
}
 
this.unprepare = function() {
this.Input = null;
this.Output = null;
this.Error = null;
}
// ...
var printNewLine = function() {
// code that prints a new line
}
 
var printString = function(params) {
// code that prints parameters
}
 
var printInteger = function(params) {
// code that prints parameters
}
 
var printBoolean = function(params) {
// code that prints parameters
}
 
var ScanNewLine = function() {
// code that looks for a newline
}
 
var ScanString = function(params) {
// code that inputs data into parameters
}
var ScanInteger = function(params) {
// code that inputs data into parameters
}
 
var ScanBoolean = function(params) {
// code that inputs data into parameters
}
// ...
}
</source>
 
===== Használat =====
 
<source lang="javascript">
function ConsoleDemo() {
var Console = null;
 
var prepare = function() {
Console = new ConsoleClass();
 
Console.prepare();
}
var unprepare = function() {
Console.unprepare();
}
 
var run = function() {
Console.printString("Hello World");
Console.printNewLine();
}
 
var main = function() {
this.prepare();
this.run();
this.unprepare();
}
}
</source>
 
=== Procedurális programozási nyelvek ===
 
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ó =====
 
<source lang="php">
<?php
// filename: console.php
 
function console_prepare() {
// code that prepares a "console"
}
function console_unprepare() {
// code that unprepares a "console"
}
 
// ...
function console_printNewLine() {
// code that ouputs a new line
}
function console_printString(/* String */ Value) {
// code that prints parameters
}
function console_printInteger(/* Integer */ Value) {
// code that prints parameters
}
function console_printBoolean(/* Boolean */ Value) {
// code that prints parameters
}
function console_scanNewLine() {
// code that looks for a new line
}
function console_scanString(/* String */ Value) {
// code that stores data into parameters
}
function console_scanInteger(/* Integer */ Value) {
// code that stores data into parameters
}
function console_scanBoolean(/* Boolean */ Value) {
// code that stores data into parameters
}
?>
</source>
 
===== Használat =====
 
<source lang="php">
<?php
// filename: consoledemo.php
 
require_once("console.php");
 
function consoledemo_prepare()
{
console_prepare();
}
function consoledemo_unprepare()
{
console_unprepare();
}
function consoledemo_execute()
{
console_printString("Hello World");
console_printNewLine();
console_scanNewLine();
}
function consoledemo_main()
{
consoledemo_prepare();
consoledemo_execute();
consoledemo_unprepare();
}
?>
</source>
 
==== C ====
 
Az alábbi példa a procedurális, névterek nélküli [[C (programozási nyelv)|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.
 
===== Modul definíció header =====
 
<source lang="c">
// filename: "consoles.h"
 
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void consoles_prepare();
void consoles_unprepare();
 
// ...
void consoles_printNewLine();
void consoles_printString(char* Value);
void consoles_printInteger(int Value);
void consoles_printBoolean(bool Value);
void consoles_scanNewLine();
void consoles_scanString(char* Value);
void consoles_scanInteger(int* Value);
void consoles_scanBoolean(bool* Value);
</source>
 
===== Modul definíció törzs =====
 
<source lang="c">
// filename: "consoles.c"
 
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <consoles.h>
void consoles_prepare() {
// code that prepares console
}
void consoles_unprepare() {
// code that unprepares console
}
 
// ...
void consoles_printNewLine() {
printf("\n");
}
void consoles_printString(char* Value) {
printf("%s", Value);
}
void consoles_printInteger(int Value) {
printf("%d", &Value);
}
void consoles_printBoolean(bool Value) {
if (Value)
{
printf("true");
}
else
{
printf("false");
}
}
void consoles_scanNewLine() {
getch();
}
void consoles_scanString(char* Value) {
scanf("%s", Value);
}
void consoles_scanInteger(int* Value) {
scanf("%d", Value);
}
void consoles_scanBoolean(bool* Value) {
char temp[512];
scanf("%s", temp);
*Value = (strcmp(Temp, "true") == 0);
}
</source>
 
===== Használat =====
 
<source lang="c">
// filename: "consoledemo.c"
 
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <consoles.h>
 
void consoledemo_prepare()
{
consoles_prepare();
}
void consoledemo_unprepare()
{
consoles_unprepare();
}
int consoledemo_execute()
{
consoles_printString("Hello World");
consoles_printNewLine();
consoles_scanNewLine();
return 0;
}
int main()
{
ErrorCode Result = 0;
consoledemo_prepare();
ErrorCode = consoledemo_execute();
consoledemo_unprepare();
return ErrorCode;
}
</source>
 
==== Procedurális Pascal ====
 
Az alábbi példa a procedurális, nem moduláris [[Pascal (programozási nyelv)|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ó =====
 
<source lang="pascal">
unit consoles;
(* filename: "consoles.pas" *)
 
uses crt;
 
procedure prepare();
begin
(* code that prepares console *)
end;
procedure unprepare();
begin
(* code that unprepares console *)
end;
 
// ...
procedure printNewLine();
begin
WriteLn();
end;
procedure printString(Value: string);
begin
Write(Value);
end;
procedure printInteger(Value: integer);
begin
Write(Value);
end;
procedure printBoolean(Value: boolean);
begin
if (Value) then
begin
Write('true');
end else
begin
Write('false');
end;
end;
procedure scanNewLine();
begin
SeekEoLn();
end;
procedure scanString(Value: string);
begin
ReadLn(Value);
end;
procedure scanInteger(Value: Integer);
begin
ReadLn(Value);
end;
procedure scanBoolean(Value: Boolean);
var temp: string;
begin
ReadLn(temp);
if (Temp = 'true') then
begin
Value := true;
end else
begin
Value := false;
end;
end;
</source>
 
===== Használat =====
 
<source lang="pascal">
program consoledemo;
// filename: "consoles.pas"
 
uses consoles;
 
procedure prepare();
begin
consoles.prepare();
end;
procedure unprepare();
begin
consoles.unprepare();
end;
 
function execute(): Integer;
begin
consoles.printString('Hello World');
consoles.printNewLine();
consoles.scanNewLine();
execute := 0;
end;
begin
prepare();
execute();
unprepare();
end.
</source>
 
== Összehasonlítás egyéb koncepciókkal ==
 
=== Néveterek (namespace) ===
 
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, hogy a részét képező globális elemek, egy metódus hívással inicializálásra vagy lezárásra kerüljenek.
 
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ány (számítógépes programozás)|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 programtervezési minta|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ő programtervezési minta|díszítő minta]]'', vagy ''[[Pehelysúlyú programtervezési minta|pehelysúlyú minta]]'' vagy akár ''[[Illesztő programtervezési minta|illesztő mintaként]]''.
 
== A modul, mint tervezési minta ==
 
A modul mintára tekinthetünk [[Létrehozási minta|létrehozási mintaként]] és [[Szerkezeti minta|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.