Шаблон модуля
Эта статья включает список литературы , связанную литературу или внешние ссылки , но ее источники остаются неясными, поскольку в ней отсутствуют встроенные цитаты . ( Июль 2014 г. ) |
В разработке программного обеспечения шаблон модуля — это шаблон проектирования, используемый для реализации концепции программных модулей , определенной модульным программированием , на языке программирования с неполной прямой поддержкой этой концепции.
Этот шаблон может быть реализован несколькими способами в зависимости от основного языка программирования, например, шаблон проектирования Singleton , объектно-ориентированные статические члены в классе и процедурные глобальные функции. В Python шаблон встроен в язык, и каждый файл .py автоматически является модулем. То же самое относится и к Ada, где пакет можно рассматривать как модуль (аналог статического класса).
Определение и структура
[ редактировать ]Шаблон проектирования модульного программного обеспечения предоставляет функции и синтаксическую структуру, определенные парадигмой модульного программирования, для языков программирования, которые имеют неполную поддержку этой концепции.
Концепция
[ редактировать ]При разработке программного обеспечения исходный код может быть организован в компоненты, выполняющие определенную функцию или содержащие все необходимое для выполнения определенной задачи. Модульное программирование — один из таких подходов.
Концепция «модуля» не полностью поддерживается во многих распространенных языках программирования.
Функции
[ редактировать ]Чтобы считать, что синглтон или любая группа связанного кода реализует этот шаблон, необходимо предоставить следующие функции:
- Часть кода должна иметь глобальный или общедоступный доступ и быть разработана для использования в качестве глобального/открытого кода. Дополнительный частный или защищенный код может выполняться основным открытым кодом.
- Модуль должен иметь функцию инициализатора, эквивалентную методу конструктора объекта или дополняющую его . Эта функция не поддерживается обычными пространствами имен .
- Модуль должен иметь функцию финализатора, эквивалентную методу деструктора объекта или дополняющую его. Эта функция не поддерживается обычными пространствами имен.
- Поддерживающим членам может потребоваться код инициализации/финализации, который выполняется функцией инициализатора/финализатора модуля.
- Большинство членов — это функции, которые выполняют операции с элементами, внешними по отношению к классу, предоставляемыми в качестве аргументов при вызове функций. Такими функциями являются «утилиты», «инструменты» или «библиотеки».
Реализации
[ редактировать ]Семантика и синтаксис каждого языка программирования могут влиять на реализацию этого шаблона.
Объектно-ориентированные языки программирования
[ редактировать ]Ява
[ редактировать ]Хотя 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
[ редактировать ]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. Однако в одном классе можно применять и комбинировать другие шаблоны проектирования.
Этот шаблон можно использовать в качестве декоратора , приспособления или адаптера .
Модуль как шаблон проектирования
[ редактировать ]Шаблон «Модуль» можно рассматривать как шаблон творения и структурный шаблон . Он управляет созданием и организацией других элементов и группирует их, как это делает структурный шаблон.
Объект, применяющий этот шаблон, может предоставить эквивалент пространства имен , обеспечивая процесс инициализации и финализации статического класса или класса со статическими членами с более чистым, кратким синтаксисом и семантикой .
Он поддерживает определенные случаи, когда класс или объект можно считать структурированными процедурными данными. И наоборот, переносите структурированные, процедурные данные, считающиеся объектно-ориентированными.
См. также
[ редактировать ]- Шаблон проектирования
- Шаблоны проектирования (Э. Гамма и др.)
- Шаблон синглтон
- Шаблон адаптера