Modulmönster - Module pattern

Inom mjukvaruteknik är modulmönstret ett designmönster som används för att implementera konceptet med programvarumoduler , definierade av modulär programmering , i ett programmeringsspråk med ofullständigt direkt stöd för konceptet.

Detta mönster kan implementeras på flera sätt beroende på värdprogrammeringsspråket, till exempel singleton-mönstret , objektorienterade statiska medlemmar i en klass och globala procedurfunktioner. I Python är mönstret inbyggt i språket, och varje .py -fil är automatiskt en modul.

Definition och struktur

Den modul designmönster ger de funktioner och syntaktiska struktur definieras av den modulära programmering paradigm till programmeringsspråk som har ofullständig stöd för konceptet.

Objektmodulmönstret uttryckt i UML.
Objektmodulmönstret uttryckt i UML .

Begrepp

I mjukvaruutveckling kan källkoden organiseras i komponenter som utför en viss funktion eller innehåller allt som är nödvändigt för att utföra en viss uppgift. Modulär programmering är en av dessa metoder.

Begreppet "modul" stöds inte fullt ut på många vanliga programmeringsspråk.

Funktioner

För att anse att en Singleton eller någon grupp av relaterad kod implementerar detta mönster måste följande funktioner tillhandahållas:

  • En del av koden måste ha global eller allmän åtkomst och vara utformad för användning som global/offentlig kod. Ytterligare privat eller skyddad kod kan köras med den allmänna huvudkoden.
  • En modul måste ha en initieringsfunktion som motsvarar eller kompletterar en objektkonstruktormetod . Den här funktionen stöds inte av vanliga namnutrymmen .
  • En modul måste ha en finaliseringsfunktion som är ekvivalent med eller komplement till en objektdestruktormetod. Den här funktionen stöds inte av vanliga namnutrymmen.
  • Stödmedlemmar kan kräva initialisering/slutförandekod som exekveras av modulens initialiserings-/finaliseringsfunktion.
  • De flesta medlemmar är funktioner som utför funktioner på element utanför klassen, som tillhandahålls som argument genom att anropa funktioner. Sådana funktioner är "verktyg", "verktyg" eller "bibliotek".

Implementeringar

Semantiken och syntaxen för varje programmeringsspråk kan påverka implementeringen av detta mönster.

Objektorienterade programmeringsspråk

Java

Även om Java stöder tanken på ett namnutrymme , en reducerad version av en modul, kan vissa scenarier dra nytta av att använda designmönstret istället för att använda namnutrymmen.

I följande exempel används singletonmönstret.

Definition
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: ...
  }
  
  // ...
  
}
Genomförande
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)

C# , liksom Java, stöder namnområden även om mönstret förblir användbart i specifika fall.

I följande exempel används singletonmönstret.

Definition
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: ...
        }
        
        // ...
    
    }
}
Genomförande
    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();
        }
    }

Prototypbaserade programmeringsspråk

JavaScript

JavaScript används ofta för att automatisera webbsidor.

Definition
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
  }
  
  // ...
  
}
Genomförande
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();
  }  
}

Procedurella programmeringsspråk

Detta mönster kan ses som en procedurförlängning till objektorienterade språk.

Även om de procedurella och modulära programmeringsparadigmen ofta används tillsammans, finns det fall där ett procedurprogrammeringsspråk kanske inte helt stöder moduler, vilket kräver en designmönsterimplementering.

PHP (procedur)

Det här exemplet gäller procedur -PHP före namnområden (introduceras i version 5.3.0). Det rekommenderas att varje medlem i en modul får ett prefix relaterat till filnamnet eller modulnamnet för att undvika identitetskollisioner.

Definition
<?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
}
Genomförande
// 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

Observera att detta exempel gäller procedur C utan namnutrymmen. Det rekommenderas att varje medlem i en modul får ett prefix relaterat till filnamnet eller modulnamnet för att undvika identitetskollisioner.

Definition header module
  // 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);
Definitionskroppsmodul
  // 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);
  }
Genomförande
  // 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;
  }

Procedurell Pascal

Observera att detta exempel gäller för procedurell icke-modulär Pascal. Många Pascal -dialekter har stöd för namnutrymme, kallad "enhet (er)". Vissa dialekter stöder också initialisering och finalisering.

Om namnutrymmen inte stöds rekommenderas att ge alla medlemsnamn ett prefix relaterat till filnamnet eller modulnamnet för att förhindra identifierarkollisioner.

Definition
  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;
Genomförande
  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.

Jämförelser med andra begrepp

Namnutrymmen

Både namnområden och moduler gör det möjligt att gruppera flera relaterade enheter med en enda identifierare, och i vissa situationer används de utbytbart. Dessa enheter kan nås globalt. Huvudsyftet med båda begreppen är detsamma.

I vissa scenarier kräver ett namnutrymme att de globala elementen som komponerar det initieras och slutförs av en funktion eller metodanrop.

I många programmeringsspråk är namnutrymmen inte direkt avsedda att stödja en initialiseringsprocess eller en finaliseringsprocess och är därför inte likvärdiga med moduler. Den begränsningen kan bearbetas på två sätt. I namnområden som stöder globala funktioner kodas en funktion för initialisering och en funktion för avslutning direkt och anropas direkt i huvudprogramkoden.

Klasser och namnområden

Klasser används ibland som eller med namnutrymmen . På programmeringsspråk som inte stöder namnområden (t.ex. JavaScript) men som stöder klasser och objekt, används klasser ofta för att ersätta namnområden. Dessa klasser är vanligtvis inte instanserade och består uteslutande av statiska medlemmar.

Singleton -klasser och namnområden

I objektorienterade programmeringsspråk där namnutrymmen är ofullständigt stödda, kan singletonmönstret användas istället för statiska medlemmar inom en klass som inte är instabil.

Förhållande till andra designmönster

Modulmönstret kan implementeras med hjälp av en specialisering av singletonmönstret. Andra designmönster kan dock tillämpas och kombineras i samma klass.

Detta mönster kan användas som dekoratör , flugvikt eller adapter .

Modul som designmönster

Modulmönstret kan betraktas som ett skapande mönster och ett strukturellt mönster . Det hanterar skapandet och organisationen av andra element och grupperar dem som det strukturella mönstret gör.

Ett objekt som tillämpar detta mönster kan ge motsvarigheten till ett namnutrymme , vilket ger initialiserings- och slutbehandlingsprocessen för en statisk klass eller en klass med statiska medlemmar renare, mer kortfattad syntax och semantik .

Den stöder specifika fall där en klass eller ett objekt kan betraktas som strukturerade, processuella data. Och tvärtom, migrera strukturerade, procedurella data och betraktas som objektorienterade.

Se även