Pular para o conteúdo

Conheça Walt Disney World

Module pattern

In software engineering, the module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language that does not support it, or only supports it, partially.

This pattern may be considered a variant of the singleton design pattern with a more specific purpose.

Contents

Definition

The goal of the Module Software Design Pattern is to provide the features & syntax structure defined by the Modular Programming Paradigm, to Programming Languages, that does not support it, at all, or support it partially.

Structure

The object module pattern expressed in UML.
The object module pattern expressed in UML.

This pattern requires 2 elements, one is the definition element, which is a group of code, single object, or single class, that applies the pattern. And, another is the implementation element, which is a group of code, single object, or single class, that uses the definition element.

An element, can be both roles, apply one pattern, and use another. Is it common for this pattern to be applied several times in an application.

Concept

In Software Development, there exist several approaches/paradigms to organize source code, grouped and separated in several components, each of which accomplishes a particular function or contains everything necessary to accomplish a particular task. Modular programming is one of those approaches and is usually applied together with procedural programming.

In many commonly used object-oriented programming languages, the concept of a "module" is not fully supported or not supported at all; object-oriented source code is commonly distributed in several files. Elements can, however, be grouped -- both physically as files in a folder and conceptually as namespaces or packages. Several programming languages supports namespaces, i.e. logically related groups of classes associated with identifiers, such as Java and C++.

Features

In order to consider a Singleton, or any group of related code, to implement this pattern, the following features must be applied:

  • When implemented by a class or object, there should be a unique instance in all the program.
  • The code should have public access, and be meant to be used as public code, not like a regular singleton, that may have private or protected scope.
  • Should have global access, or to be members of a entity with a global access.
  • When implemented as Object Oriented, classes will, preferably, not meant to be extended.
  • Should have a initializer function, that may be the same, equivalent, or complementary, to an object constructor method. This feature is not supported by regular namespaces.
  • Should have a finalizer function, may be the same, equivalent, or complementary, to an object destructor method. This feature is not supported by regular namespaces.
  • Supports & encapsulates several related members, that maybe singletons as well.
  • In case of supporting members, those elements, may require initialization code, and may require finalization code, that is executed, by the initializer function & the finalizer function, of the module, itself.
  • Most members are functions that perform operations, on elements external to the class, provided as parameters. Those functions are meant to be frequently used as "utilities", "tools" or "libraries".

Similarities & Differences with Similar Concepts

Namespaces versus Modules

Both, Namespaces and Modules, allow to group several related entities by a single identifier, and in some situations, maybe used interchangeably. Those entities, can be globally accessed. Therefore, the main purpose of both concepts its be the same.

There are scenarios where a namespace require that the global elements, that compose it, to be initialized, and sometimes, some finalization process, calling a function or method.

Since a namespace, its only intended to contain elements, and not to perform any behavior, the module is intended to support, both, the initialization & finalization process, also.

Classes versus Namespaces

Classes are used, sometimes, as Namespaces, or used, both, together. In some programming languages that doesn't support namespaces (example: previous versions of PHP, JavaScript), but, classes & objects, classes are used by themselves, allow access to their sub-elements, without directly instantiating the class into objects.

In those circumstances, classes & objects, are used to implement the features of a namespace, or a module.

In order to support this, sometimes; the static compiler feature, or compiler modifier, its provided to the class, or, to some, of the particular members of the class.

Singletons versus Namespaces

In programming languages where namespaces are not supported, or partially supported, and individual members from a class cannot be accessed, the solution is to generate a singleton object from an specific class, and used as a singleton pattern.

Relations with other Design Patterns

The Module Pattern can be implemented using a specialization of the Singleton Design Pattern. However, other Design Patterns may applied & combined, in the same class, as well.

This pattern can be used as a Decorator, a Flyweight, or an Adapter.

Implementations of the Module Pattern in different Programming Languages

The semantics & syntax of each programming language, may cause the implementation of this pattern to differ. The version of the programming language, supporting new features, may also cause to have different implementations, for the same language.

The following examples show a possible implementation of this pattern, but, there could be others, for the same language, language version, & compiler.

Note, that in some cases, the wrapper software pattern, has also been applied, but, is not a requisite.

Examples of Implementations in Object Oriented Programming Languages

Java

Although Java support the notion of namespaces, a reduced version of a module, there are some scenarios, where a software developer, may want to apply this pattern, in this language.

Definition Module

package consoles;
 
public final class mainmodule {
 
  private mainmodule Singleton  = null;
 
  public InputStream input  = null;
  public PrintStream output = null;
  public PrintStream error  = null;
 
  public mainmodule() {
    // does nothing on purpose !!!
  }
 
  // ...
 
  public 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(Integer 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(Integer Value) {
    // to-do: ...
  }
 
  public void ScanBoolean(Boolean Value) {
    // to-do: ...
  }
 
  // ...
 
}

Implementation Module

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(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#, as well as Java, support the notion of namespaces, a reduced version of a module, there are some scenarios, where a software developer, may want to apply this pattern.

Definition Module

using System;
using System.IO;
using System.Text;
 
namespace Consoles {
 
  public InputStream  input  = null;
  public OutputStream output = null;
  public ErrorStream  error  = null;
 
  public sealed class MainModule {
    private static Singleton = null;
 
    // ...
 
    public MainModule () {
      // does nothing on purpose !!!
    }
 
    // ...
 
    public 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: ...
    }
 
    // ...
 
  }
}

Implementation Module

  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();
    }
  }

Example Implementations in Prototype-Based Programming Languages

JavaScript

Definition Module

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(name) {
    this.Input  = new InputStream();
    this.Output = new OutputStream();
    this.Error  = new ErrorStream();
  }
 
  // ...
 
  var printNewLine = function(name) {
    // to-do: ...
  }
 
  var printString = function(name) {
    // to-do: ...
  }
 
  var printInteger = function(name) {
    // to-do: ...
  }
 
  var printBoolean = function(name) {
    // to-do: ...
  }
 
  var ScanNewLine = function(name) {
    // to-do: ...
  }
 
  var ScanString = function(name) {
    // to-do: ...
  }
 
  var ScanInteger = function(name) {
    // to-do: ...
  }
 
  var ScanBoolean = function(name) {
    // to-do: ...
  }
 
  // ...
 
}

Implementation Module

function ConsoleDemo() {
  var Console  = null;
 
  var prepare = function(name) {
    Console  = new ConsoleClass();
 
    Console.prepare();
  }
 
  var unprepare = function(name) {
    Console.unprepare();  
  }
 
  var run = function(name) {
    // echo "Hello World";
  }
 
  var main = function(name) {
    this.prepare();
    this.run();
    this.unprepare();
  }  
}

Example Implementations in Procedural Programming Languages

This pattern, may be seen, as a Procedural extension to Object Oriented Languages. But, also applies to other scenarios.

Although, Procedural & Modular Programming Paradigms, have been commonly used together, there are cases where a Procedural Programming Language, may not fully support modules.

PHP (as procedural)

Note that this example applies to procedural, without namespaces, previous versions of PHP.

Definition Module

<?php
  // filename: console.php
 
  /* void */ console_prepare() {
    // to-do: ...
  }
 
  /* void */ console_unprepare() {
    // to-do: ...
  } 
 
  // ...
 
  /* void */ console_printNewLine() {
    // to-do: ...
  }
 
  /* void */ console_printString(/* String */ Value) {
          // to-do: ...
  }
 
  /* void */ console_printInteger(/* Integer */ Value) {
    // to-do: ...
  }
 
  /* void */ console_printBoolean(/* Boolean */ Value) {
    // to-do: ...
  }
 
  /* void */ console_scanNewLine() {
    // to-do: ...
  }
 
  /* void */ console_scanString(/* String */ Value) {
    // to-do: ...
  }
 
  /* void */ console_scanInteger(/* Integer */ Value) {
    // to-do: ...
  }
 
  /* void */ console_scanBoolean(/* Boolean */ Value) {
    // to-do: ...
  }
?>

Implementation Module

<?php
    // filename: consoledemo.php
 
    require_once("console.php");
 
    /* void */ consoledemo_prepare()
    {
      console_prepare();
    }
 
    /* void */ consoledemo_unprepare()
    {
      console_unprepare();
    }
 
    /* void */ consoledemo_execute()
    {
      console_printString("Hello World");
      console_printNewLine();
        console_scanNewLine();
    }
 
    /* void */ consoledemo_main()
    {
      consoledemo_prepare();
      consoledemo_execute();
      consoledemo_unprepare();
    }
?>

"Pure C" or "Plain C"

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);

Definition Body Module

  // filename: "consoles.c"
 
  #include <stdio.h>
  #include <string.h>
  #include <ctype.h>
  #include <consoles.h>
 
  void consoles_prepare() {
    // to-do: ...
  }
 
  void consoles_unprepare() {
    // to-do: ...
  } 
 
  // ...
 
  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);
  }

Implementation Module

  // filename: "consoles.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;
  }

Reasons to consider a "Module" a Design Pattern, by itself

The Module pattern can be consider both as a Creational Pattern, and as Structural Pattern. It allows to manage the creation of other elements, and at the same time, organize other elements, and group them as the Structural Pattern does.

An object that apples this pattern, can perform the functionality of a namespace, providing the initialization & finalization process of a static class, or a class with static members; with a more clean, concise syntax, and semantics.

Supports specific cases, where a class or object can be considered as Structured, Procedural Data. And, vice-versa, migrate Structured, Procedural Data, and considered as Object Oriented.

See also

  • Design Patterns, the highly influential book
  • Design pattern, overview of design patterns in general
  • Singleton pattern, a pattern to support single instances of objects, usually in global scope.
  • Adapter pattern, a pattern to allow the interface of a class, to be used, as the interface of another class. Also called Wrapper or Translator.


Personal tools
  • Log in / create account
Namespaces

Variants
Actions
Navigation
Toolbox
Print/export