Jump to content

Шаблон модуля

В разработке программного обеспечения шаблон модуля — это шаблон проектирования, используемый для реализации концепции программных модулей , определенной модульным программированием , на языке программирования с неполной прямой поддержкой этой концепции.

Этот шаблон может быть реализован несколькими способами в зависимости от основного языка программирования, например, шаблон проектирования Singleton , объектно-ориентированные статические члены в классе и процедурные глобальные функции. В Python шаблон встроен в язык, и каждый файл .py автоматически является модулем. То же самое относится и к Ada, где пакет можно рассматривать как модуль (аналог статического класса).

Определение и структура

[ редактировать ]

Шаблон проектирования модульного программного обеспечения предоставляет функции и синтаксическую структуру, определенные парадигмой модульного программирования, для языков программирования, которые имеют неполную поддержку этой концепции.

Шаблон объектного модуля, выраженный в UML.
Шаблон объектного модуля, выраженный в UML .

Концепция

[ редактировать ]

При разработке программного обеспечения исходный код может быть организован в компоненты, выполняющие определенную функцию или содержащие все необходимое для выполнения определенной задачи. Модульное программирование — один из таких подходов.

Концепция «модуля» не полностью поддерживается во многих распространенных языках программирования.

Чтобы считать, что синглтон или любая группа связанного кода реализует этот шаблон, необходимо предоставить следующие функции:

  • Часть кода должна иметь глобальный или общедоступный доступ и быть разработана для использования в качестве глобального/открытого кода. Дополнительный частный или защищенный код может выполняться основным открытым кодом.
  • Модуль должен иметь функцию инициализатора, эквивалентную методу конструктора объекта или дополняющую его . Эта функция не поддерживается обычными пространствами имен .
  • Модуль должен иметь функцию финализатора, эквивалентную методу деструктора объекта или дополняющую его. Эта функция не поддерживается обычными пространствами имен.
  • Поддерживающим членам может потребоваться код инициализации/финализации, который выполняется функцией инициализатора/финализатора модуля.
  • Большинство членов — это функции, которые выполняют операции с элементами, внешними по отношению к классу, предоставляемыми в качестве аргументов при вызове функций. Такими функциями являются «утилиты», «инструменты» или «библиотеки».

Реализации

[ редактировать ]

Семантика и синтаксис каждого языка программирования могут влиять на реализацию этого шаблона.

Объектно-ориентированные языки программирования

[ редактировать ]

Хотя Java поддерживает понятие пространства имен , сокращенной версии модуля, в некоторых сценариях лучше использовать шаблон проектирования вместо использования пространств имен.

В следующем примере используется шаблон Singleton.

Определение
[ редактировать ]
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: ...
  }
  
  // ...
  
}
Выполнение
[ редактировать ]
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 Sharp .NET)

[ редактировать ]

C# , как и Java, поддерживает пространства имен, хотя в определенных случаях этот шаблон остается полезным.

В следующем примере используется шаблон Singleton.

Определение
[ редактировать ]
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: ...
    }

    // ...
}
Выполнение
[ редактировать ]
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();
    }
}

Языки программирования на основе прототипов

[ редактировать ]

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
  }
  
  // ...
  
}
Выполнение
[ редактировать ]
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();
  }  
}

Процедурные языки программирования

[ редактировать ]

Этот шаблон можно рассматривать как процедурное расширение объектно-ориентированных языков.

Хотя процедурная и модульная парадигмы программирования часто используются вместе, бывают случаи, когда процедурный язык программирования может не полностью поддерживать модули, что требует реализации шаблона проектирования.

PHP (процедурный)

[ редактировать ]

Этот пример применим к процедурному PHP перед пространствами имен (введено в версии 5.3.0). Рекомендуется, чтобы каждому члену модуля присваивался префикс, связанный с именем файла или имени модуля, чтобы избежать конфликтов идентификаторов.

Определение
[ редактировать ]
<?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
}
Выполнение
[ редактировать ]
// 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 без пространств имен. Рекомендуется, чтобы каждому члену модуля присваивался префикс, связанный с именем файла или именем модуля, чтобы избежать конфликтов идентификаторов.

Модуль заголовка определения
[ редактировать ]
// 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);
Модуль определения тела
[ редактировать ]
// 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) {
  printf((Value) ? ("true") : ("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);
}
Выполнение
[ редактировать ]
// 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;
}

Процедурный Паскаль

[ редактировать ]

Обратите внимание, что этот пример относится к процедурному немодулярному Паскалю. Многие диалекты Паскаля поддерживают пространство имен, называемое «единица(и)». Некоторые диалекты также поддерживают инициализацию и финализацию.

Если пространства имен не поддерживаются, рекомендуется присвоить всем именам членов префикс, связанный с именем файла или именем модуля, чтобы предотвратить конфликты идентификаторов.

Определение
[ редактировать ]
  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;
Выполнение
[ редактировать ]
  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.

Сравнения с другими концепциями

[ редактировать ]

Пространства имен

[ редактировать ]

И пространства имен , и модули позволяют группировать несколько связанных объектов по одному идентификатору, а в некоторых ситуациях использовать их как взаимозаменяемые. Доступ к этим объектам может быть глобальным. Основная цель обеих концепций одна и та же.

В некоторых сценариях пространство имен требует, чтобы глобальные элементы, составляющие его, были инициализированы и завершены вызовом функции или метода.

Во многих языках программирования пространства имен не предназначены напрямую для поддержки процесса инициализации или финализации и поэтому не эквивалентны модулям. Это ограничение можно обойти двумя способами. В пространствах имен , поддерживающих глобальные функции, функция инициализации и функция финализации кодируются напрямую и вызываются непосредственно в основном коде программы.

Классы и пространства имен

[ редактировать ]

Классы иногда используются вместе с пространствами имен . В языках программирования, которые не поддерживают пространства имен (например, JavaScript), но поддерживают классы и объекты, классы часто используются для замены пространств имен. Эти классы обычно не создаются и состоят исключительно из статических членов.

Одноэлементные классы и пространства имен

[ редактировать ]

В объектно-ориентированных языках программирования, где пространства имен поддерживаются не полностью, шаблон Singleton может использоваться вместо статических членов в классе, не допускающем создания экземпляров.

Связь с другими шаблонами проектирования

[ редактировать ]

Шаблон модуля можно реализовать, используя специализацию шаблона Singleton. Однако в одном классе можно применять и комбинировать другие шаблоны проектирования.

Этот шаблон можно использовать в качестве декоратора , приспособления или адаптера .

Модуль как шаблон проектирования

[ редактировать ]

Шаблон «Модуль» можно рассматривать как шаблон творения и структурный шаблон . Он управляет созданием и организацией других элементов и группирует их, как это делает структурный шаблон.

Объект, применяющий этот шаблон, может предоставить эквивалент пространства имен , обеспечивая процесс инициализации и финализации статического класса или класса со статическими членами с более чистым, кратким синтаксисом и семантикой .

Он поддерживает определенные случаи, когда класс или объект можно считать структурированными процедурными данными. И наоборот, переносите структурированные, процедурные данные, считающиеся объектно-ориентированными.

См. также

[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: e07561109bf78133a4a6eba9adf3e454__1686120120
URL1:https://arc.ask3.ru/arc/aa/e0/54/e07561109bf78133a4a6eba9adf3e454.html
Заголовок, (Title) документа по адресу, URL1:
Module pattern - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)