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.

Az objektummodul mintája UML -ben kifejezve.
Az objektummodul mintája UML -ben kifejezve .

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