Modul minta - Module pattern
A szoftverfejlesztésben a modulminta egy tervezési minta , amelyet a moduláris programozás által meghatározott szoftvermodulok koncepciójának megvalósítására használnak egy programozási nyelven , a koncepció hiányos közvetlen támogatásával.
Ez a minta a gazda programozási nyelvétől függően többféleképpen is megvalósítható, mint például az egyedi tervezési minta , az objektum-orientált statikus tagok egy osztályban és az eljárási globális függvények. A Pythonban a minta a nyelvbe van beépítve, és minden .py fájl automatikusan modul.
Meghatározás és szerkezet
A modul szoftver tervezési mintája biztosítja a moduláris programozási paradigma által meghatározott funkciókat és szintaktikai struktúrát azoknak a programozási nyelveknek, amelyek hiányosan támogatják a koncepciót.
Koncepció
A szoftverfejlesztés során a forráskód olyan összetevőkbe rendezhető, amelyek egy adott funkciót ellátnak, vagy mindent tartalmaznak, ami egy adott feladat elvégzéséhez szükséges. A moduláris programozás az egyik ilyen módszer.
A "modul" fogalmát sok közös programozási nyelv nem támogatja teljesen.
Jellemzők
Annak érdekében, hogy egy Singleton vagy bármely kapcsolódó kódcsoport megvalósítsa ezt a mintát, a következő szolgáltatásokat kell biztosítani:
- A kód egy részének globális vagy nyilvános hozzáféréssel kell rendelkeznie, és globális/nyilvános kódként való használatra kell tervezni. További privát vagy védett kód futtatható a fő nyilvános kóddal.
- A modulnak rendelkeznie kell egy inicializáló funkcióval, amely egyenértékű vagy kiegészíti az objektumkonstruktor módszerét. Ezt a funkciót nem támogatják a szokásos névterek .
- A modulnak véglegesítő funkcióval kell rendelkeznie, amely egyenértékű vagy kiegészíti az objektumpusztító módszert. Ezt a funkciót nem támogatják a szokásos névterek.
- A támogató tagok igényelhetnek inicializáló/véglegesítő kódot, amelyet a modul inicializáló/véglegesítő funkciója hajt végre.
- A legtöbb tag olyan függvény, amely az osztályon kívüli elemeken hajt végre műveleteket, argumentumként a függvények meghívásával. Ilyen funkciók a "segédprogramok", "eszközök" vagy "könyvtárak".
Megvalósítások
Az egyes programozási nyelvek szemantikája és szintaxisa befolyásolhatja ennek a mintának a megvalósítását.
Objektum-orientált programozási nyelvek
Jáva
Bár a Java támogatja a névtér fogalmát, a modul csökkentett változatát, egyes forgatókönyvek előnyösek a tervezési minta alkalmazásával a névterek használata helyett.
A következő példa az egyszeres mintát használja.
Meghatározás
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;
private MainModule() {
// does nothing on purpose !!!
}
// ...
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: ...
}
// ...
}
Végrehajtás
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();
}
}
C# (C Sharp .NET)
A C# a Java -hoz hasonlóan támogatja a névtereket, bár a minta bizonyos esetekben hasznos marad.
A következő példa az egyszeres mintát használja.
Meghatározás
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 () {
// does nothing on purpose !!!
}
// ...
public static 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: ...
}
// ...
}
}
Végrehajtás
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();
}
}
Prototípus-alapú programozási nyelvek
JavaScript
A JavaScriptet általában weboldalak automatizálására használják.
Meghatározás
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
}
// ...
}
Végrehajtás
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();
}
}
Procedurális programozási nyelvek
Ez a minta az objektum-orientált nyelvek eljárási kiterjesztésének tekinthető.
Bár az eljárási és a moduláris programozási paradigmákat gyakran együtt használják, vannak esetek, amikor egy eljárási programozási nyelv nem támogatja teljes mértékben a modulokat, ezért tervezési minta implementációt igényel.
PHP (eljárási)
Ez a példa a névterek előtti eljárási PHP -re vonatkozik (bevezetve az 5.3.0 verzióba). Az azonosítók ütközésének elkerülése érdekében ajánlott, hogy a modul minden tagja kapjon egy előtagot a fájlnévhez vagy a modulnévhez kapcsolódóan.
Meghatározás
<?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 outputs 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
}
Végrehajtás
// 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();
}
C
Ne feledje, hogy ez a példa a névterek nélküli C eljárásra vonatkozik . Javasoljuk, hogy az azonosítók ütközésének elkerülése érdekében a modul minden tagja kapjon a fájlnévhez vagy a modulnévhez kapcsolódó előtagot.
Definíció fejléc modul
// 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);
Definíciós testmodul
// 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);
}
Végrehajtás
// 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;
}
Eljárási Pascal
Vegye figyelembe, hogy ez a példa az eljárási nem moduláris Pascalra vonatkozik. Sok Pascal -nyelvjárás rendelkezik névtámogatással, amelyet "egységnek" neveznek. Néhány nyelvjárás támogatja az inicializálást és a véglegesítést is.
Ha a névterek nem támogatottak, akkor az azonosítók ütközésének elkerülése érdekében ajánlott minden tagnevet a fájlnévhez vagy a modulnévhez kapcsolódó előtaggal ellátni.
Meghatározás
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;
Végrehajtás
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.
Összehasonlítás más fogalmakkal
Névterek
Mind a névterek, mind a modulok lehetővé teszik több kapcsolódó entitás csoportosítását egyetlen azonosító alapján, és bizonyos esetekben felcserélhető módon. Ezek az entitások globálisan hozzáférhetők. Mindkét fogalom fő célja ugyanaz.
Bizonyos esetekben a névtér megköveteli, hogy az azt alkotó globális elemeket egy függvény vagy metódushívás inicializálja és véglegesítse.
Sok programozási nyelvben a névterek nem közvetlenül az inicializálási folyamat és a véglegesítési folyamat támogatására szolgálnak, ezért nem egyenértékűek a modulokkal. Ezt a korlátozást kétféleképpen lehet megkerülni. A globális függvényeket támogató névterekben az inicializálási és a véglegesítési függvényeket közvetlenül kódolják, és közvetlenül a fő programkódban hívják meg.
Osztályok és névterek
Az osztályokat néha névterekként vagy névtérként használják . Azokban a programozási nyelvekben, amelyek nem támogatják a névtereket (pl. JavaScript), de támogatják az osztályokat és objektumokat, az osztályokat gyakran használják a névterek helyett. Ezek az osztályok általában nem példányosak, és kizárólag statikus tagokból állnak.
Singleton osztályok és névterek
Azok az objektum-orientált programozási nyelvek, ahol a névterek nem teljes mértékben támogatottak, az egyszeres minta használható a nem példányosítható osztályon belüli statikus tagok helyett.
Kapcsolat más tervezési mintákkal
A modulminta kivitelezhető az egyszeres minta specializációjával. Azonban más tervezési minták is alkalmazhatók és kombinálhatók ugyanabban az osztályban.
Ez a minta díszítőként , légysúlyként vagy adapterként használható .
A modul mint tervezési minta
A modul mintázat alkotási mintának és szerkezeti mintának tekinthető . Más elemek létrehozását és szervezését kezeli, és a strukturális mintázat szerint csoportosítja.
Az ezt a mintát alkalmazó objektum egy névtér megfelelőjét nyújthatja , biztosítva egy statikus osztály vagy egy osztály inicializálási és véglegesítési folyamatát, amely tisztább, tömörebb szintaxissal és szemantikával rendelkezik .
Támogatja azokat az egyedi eseteket, amikor egy osztály vagy objektum strukturált, eljárási adatnak tekinthető. És fordítva, migrálja a strukturált, eljárási adatokat, és objektum-orientáltnak tekinti.
Lásd még
- Tervezési minta
- Tervezési minták (E. Gamma et al.)
- Singleton minta
- Adapter minta