모듈 패턴
Module pattern소프트웨어 엔지니어링에서 모듈 패턴은 모듈 프로그래밍에 의해 정의된 소프트웨어 모듈의 개념을 구현하기 위해 사용되는 설계 패턴으로, 개념에 대한 직접 지원이 불완전한 프로그래밍 언어로 사용된다.
이 패턴은 싱글톤 디자인 패턴, 클래스의 객체 지향 정적 멤버, 절차상의 글로벌 기능 등 호스트 프로그래밍 언어에 따라 여러 가지 방법으로 구현될 수 있다.파이톤에서는 패턴이 언어에 내장되어 있으며, 각각의 .py 파일은 자동으로 모듈이다.패키지가 모듈(정적 등급과 유사)으로 간주될 수 있는 에이다에게도 마찬가지다.
정의 & 구조
모듈 소프트웨어 설계 패턴은 개념에 대한 불완전한 지원을 가지고 있는 프로그래밍 언어에 모듈형 프로그래밍 패러다임에 의해 정의된 특징과 구문 구조를 제공한다.
개념
소프트웨어 개발에서 소스 코드는 특정 기능을 수행하거나 특정 업무를 수행하는 데 필요한 모든 것을 포함하는 구성요소로 구성될 수 있다.모듈형 프로그래밍은 그러한 접근방식들 중 하나이다.
"모듈"의 개념은 많은 공통 프로그래밍 언어에서 완전히 지원되지는 않는다.
특징들
Singleton 또는 관련 코드 그룹이 이 패턴을 구현한다는 점을 고려하려면 다음 기능이 제공되어야 한다.
- 코드의 일부는 글로벌 또는 공개 액세스 권한이 있어야 하며 글로벌/공공 코드로 사용하도록 설계되어야 한다.추가적인 비공개 또는 보호 코드는 주 공개 코드에 의해 실행될 수 있다.
- 모듈은 물체 생성자 방법과 동등하거나 보완적인 이니셜라이저 함수를 가져야 한다.이 기능은 일반 네임스페이스에서 지원되지 않는다.
- 모듈은 물체 소멸기 방법과 동일하거나 보완하는 파이널라이저 함수를 가져야 한다.이 기능은 일반 네임스페이스에서 지원되지 않는다.
- 지원 멤버는 모듈의 이니셜라이저/파이널라이저 기능에 의해 실행되는 초기화/최종화 코드를 요구할 수 있다.
- 대부분의 멤버는 클래스의 외부 요소에 대한 연산을 수행하는 함수로서, 함수를 호출하여 인수로 제공된다.이러한 기능은 "유틸리티", "도구" 또는 "도서관"이다.
구현
각 프로그래밍 언어의 의미론과 구문은 이 패턴의 구현에 영향을 미칠 수 있다.
객체 지향 프로그래밍 언어
자바
자바에서는 모듈의 축소판인 네임스페이스의 개념을 지원하지만, 일부 시나리오에서는 네임스페이스를 사용하는 대신 설계 패턴을 채택하여 이익을 얻는다.
다음 예제는 싱글톤 패턴을 사용한다.
정의
꾸러미 콘솔; 수입하다 java.io.입력스트림; 수입하다 java.io.프린트스트림; 공중의 최종의 계급 메인모듈 { 사유의 정태의 메인모듈 싱글톤 = 무효의; 공중의 입력스트림 입력하다 = 무효의; 공중의 프린트스트림 생산량 = 무효의; 공중의 프린트스트림 착오 = 무효의; 사유의 메인모듈() { // 일부러 아무 것도 안 해!!! } // ... 공중의 정태의 메인모듈 getSingleton() { 만일 (메인모듈.싱글톤 == 무효의) { 메인모듈.싱글톤 = 새로운 메인모듈(); } 돌아오다 메인모듈.싱글톤; } // ... 공중의 공허하게 하다 준비하다() { //System.out.println("컨설턴스::prepare();"); 이.입력하다 = 새로운 입력스트림(); 이.생산량 = 새로운 프린트스트림(); 이.착오 = 새로운 프린트스트림(); } 공중의 공허하게 하다 꾸밈이 없는() { 이.생산량 = 무효의; 이.입력하다 = 무효의; 이.착오 = 무효의; //System.out.println("컨설턴스::unprepare();"); } // ... 공중의 공허하게 하다 printNewLine() { 시스템.밖으로.인쇄하다(); } 공중의 공허하게 하다 printString(끈 가치를 매기다) { 시스템.밖으로.인쇄하다(가치를 매기다); } 공중의 공허하게 하다 프린트인테거(인트로 가치를 매기다) { 시스템.밖으로.인쇄하다(가치를 매기다); } 공중의 공허하게 하다 printBoolean(부울 가치를 매기다) { 시스템.밖으로.인쇄하다(가치를 매기다); } 공중의 공허하게 하다 scanNewLine() { // 할 일: ... } 공중의 공허하게 하다 스캔스트링(끈 가치를 매기다) { // 할 일: ... } 공중의 공허하게 하다 scanInteger(인트로 가치를 매기다) { // 할 일: ... } 공중의 공허하게 하다 scanBoolean(부울 가치를 매기다) { // 할 일: ... } // ... } 실행
수입하다 콘솔*; 계급 콘솔데모 { 공중의 정태의 메인모듈 위로하다 = 무효의; 공중의 정태의 공허하게 하다 준비하다() { 위로하다 = 메인모듈.getSingleton(); 위로하다.준비하다(); } 공중의 정태의 공허하게 하다 꾸밈이 없는() { 위로하다.꾸밈이 없는(); } 공중의 정태의 공허하게 하다 처형하다(끈[] 아그) { 위로하다.printString("헬로 월드"); 위로하다.printNewLine(); 위로하다.scanNewLine(); } 공중의 정태의 공허하게 하다 본래의(끈[] 아그) { 준비하다(); 처형하다(아그); 꾸밈이 없는(); } } C#(C Sharp).네트)
C#는 자바와 마찬가지로 네임스페이스를 지원하지만, 그 패턴은 특정 경우에 유용하다.
다음 예제는 싱글톤 패턴을 사용한다.
정의
사용. 시스템; 사용. 시스템.IO; 사용. 시스템.텍스트; 네임스페이스 콘솔; 공중의 봉인된 계급 메인모듈 { 사유의 정태의 메인모듈 싱글턴 = 무효의; 공중의 입력스트림 입력하다 = 무효의; 공중의 출력스트림 생산량 = 무효의; 공중의 에러스트림 착오 = 무효의; // ... 공중의 메인모듈() { // 일부러 아무 것도 안 해!!! } // ... 공중의 정태의 메인모듈 겟싱글턴() { 만일 (메인모듈.싱글턴 == 무효의) { 메인모듈.싱글턴 = 새로운 메인모듈(); } 돌아오다 메인모듈.싱글턴; } // ... 공중의 공허하게 하다 준비하다() { //시스템.WriteLine("console::prepare();"); 이.입력하다 = 새로운 입력스트림(); 이.생산량 = 새로운 출력스트림(); 이.착오 = 새로운 에러스트림(); } 공중의 공허하게 하다 언프패어() { 이.생산량 = 무효의; 이.입력하다 = 무효의; 이.착오 = 무효의; //시스템.WriteLine("console::unprepare();)"; } // ... 공중의 공허하게 하다 인쇄뉴라인() { 시스템.콘솔.WriteLine(""); } 공중의 공허하게 하다 프린트스트링(끈 가치) { 시스템.콘솔.쓰다(가치); } 공중의 공허하게 하다 PrintInteger(정수 가치) { 시스템.콘솔.쓰다(가치); } 공중의 공허하게 하다 PrintBoolean(부울 가치) { 시스템.콘솔.쓰다(가치); } 공중의 공허하게 하다 스캔뉴라인() { // 할 일: ... } 공중의 공허하게 하다 스캔스트링(끈 가치) { // 할 일: ... } 공중의 공허하게 하다 스캔인테거(정수 가치) { // 할 일: ... } 공중의 공허하게 하다 ScanBoolean(부울 가치) { // 할 일: ... } // ... } 실행
계급 콘솔데모 { 공중의 정태의 콘솔.메인모듈 콘솔 = 무효의; 공중의 정태의 공허하게 하다 준비하다() { 콘솔 = 콘솔.메인모듈.겟싱글턴(); 콘솔.준비하다(); } 공중의 정태의 공허하게 하다 언프패어() { 콘솔.언프패어(); } 공중의 정태의 공허하게 하다 실행() { 콘솔.프린트스트링("헬로 월드"); 콘솔.인쇄뉴라인(); 콘솔.스캔뉴라인(); } 공중의 정태의 공허하게 하다 메인() { 준비하다(); 실행(아그); 언프패어(); } } 프로토타입 기반 프로그래밍 언어
자바스크립트
자바스크립트는 웹 페이지를 자동화하는 데 일반적으로 사용된다.
정의
기능을 발휘하다 콘솔 클래스() { 시합을 하다 입력 = 무효의; 시합을 하다 출력 = 무효의; 시합을 하다 오류 = 무효의; // ... 이.준비하다 = 기능을 발휘하다() { 이.입력 = 새로운 입력스트림(); 이.출력 = 새로운 출력스트림(); 이.오류 = 새로운 에러스트림(); } 이.꾸밈이 없는 = 기능을 발휘하다() { 이.입력 = 무효의; 이.출력 = 무효의; 이.오류 = 무효의; } // ... 시합을 하다 printNewLine = 기능을 발휘하다() { // 새 줄을 인쇄하는 코드 } 시합을 하다 printString = 기능을 발휘하다(모조품) { // 매개 변수를 인쇄하는 코드 } 시합을 하다 프린트인테거 = 기능을 발휘하다(모조품) { // 매개 변수를 인쇄하는 코드 } 시합을 하다 printBoolean = 기능을 발휘하다(모조품) { // 매개 변수를 인쇄하는 코드 } 시합을 하다 스캔뉴라인 = 기능을 발휘하다() { // 새로운 라인을 찾는 코드 } 시합을 하다 스캔스트링 = 기능을 발휘하다(모조품) { // 데이터를 매개변수에 입력하는 코드 } 시합을 하다 스캔인테거 = 기능을 발휘하다(모조품) { // 데이터를 매개변수에 입력하는 코드 } 시합을 하다 ScanBoolean = 기능을 발휘하다(모조품) { // 데이터를 매개변수에 입력하는 코드 } // ... } 실행
기능을 발휘하다 콘솔데모() { 시합을 하다 콘솔 = 무효의; 시합을 하다 준비하다 = 기능을 발휘하다() { 콘솔 = 새로운 콘솔 클래스(); 콘솔.준비하다(); } 시합을 하다 꾸밈이 없는 = 기능을 발휘하다() { 콘솔.꾸밈이 없는(); } 시합을 하다 달리다 = 기능을 발휘하다() { 콘솔.printString("헬로 월드"); 콘솔.printNewLine(); } 시합을 하다 본래의 = 기능을 발휘하다() { 이.준비하다(); 이.달리다(); 이.꾸밈이 없는(); } } 절차 프로그래밍 언어
이러한 패턴은 객체 지향 언어에 대한 절차적 확장이라고 볼 수 있다.
절차적 및 모듈적 프로그래밍 패러다임이 함께 사용되는 경우가 많지만 절차적 프로그래밍 언어가 모듈을 완전히 지원하지 못하는 경우가 있으므로 설계 패턴 구현이 필요하다.
PHP(절차적)
이 예는 네임스페이스 이전 절차 PHP에 적용된다(버전 5.3.0에서 소개).식별자 충돌을 피하기 위해 모듈의 각 구성원에 파일 이름 또는 모듈 이름과 관련된 접두사를 부여할 것을 권장한다.
정의
<?php // 파일 이름: 콘솔.php 기능을 발휘하다 console_properties() { // "준비"를 준비하는 코드 } 기능을 발휘하다 console_preare() { // "불완전한" 코드 } // ... 기능을 발휘하다 console_printNewLine() { // 새 라인을 출력하는 코드 } 기능을 발휘하다 console_printString(/* 문자열 */ 가치) { // 매개 변수를 인쇄하는 코드 } 기능을 발휘하다 console_print정수(/* 정수 */ 가치) { // 매개 변수를 인쇄하는 코드 } 기능을 발휘하다 console_printBoolean(/* 부울 */ 가치) { // 매개 변수를 인쇄하는 코드 } 기능을 발휘하다 console_scanNewLine() { // 새로운 라인을 찾는 코드 } 기능을 발휘하다 console_scanString(/* 문자열 */ 가치) { // 데이터를 매개 변수에 저장하는 코드 } 기능을 발휘하다 console_scan정수(/* 정수 */ 가치) { // 데이터를 매개 변수에 저장하는 코드 } 기능을 발휘하다 콘솔_scanBoolean(/* 부울 */ 가치) { // 데이터를 매개 변수에 저장하는 코드 } 실행
// filename: pleasedemo.php 필요_한 번("reason.php"); 기능을 발휘하다 orpelenemo_prepare() { console_properties(); } 기능을 발휘하다 위안드메모_unprepare() { console_preare(); } 기능을 발휘하다 orpelenemo_execute() { console_printString("헬로 월드"); console_printNewLine(); console_scanNewLine(); } 기능을 발휘하다 oreneredemo_main() { orpelenemo_prepare(); orpelenemo_execute(); 위안드메모_unprepare(); } C
이 예는 네임스페이스가 없는 절차 C에 적용된다.식별자 충돌을 피하기 위해 모듈의 각 구성원에 파일 이름 또는 모듈 이름과 관련된 접두사를 부여할 것을 권장한다.
정의 헤더 모듈
// 파일 이름: "filename.h" #include <stdio.h> #include < 현악기>h> #include <ctype.h> 공허하게 하다 consoles_properties(); 공허하게 하다 consoles_preare(); // ... 공허하게 하다 console_printNewLine(); 공허하게 하다 console_printString(마를 뜨다* 가치); 공허하게 하다 consoles_print정수(인트로 가치); 공허하게 하다 console_printBoolean(바가지 긁다 가치); 공허하게 하다 console_scanNewLine(); 공허하게 하다 console_scanString(마를 뜨다* 가치); 공허하게 하다 console_scanInteger(인트로* 가치); 공허하게 하다 콘솔_scanBoolean(바가지 긁다* 가치); 정의 본문 모듈
// 파일 이름: "filename.c" #include <stdio.h> #include < 현악기>h> #include <ctype.h> #include <consoles.h> 공허하게 하다 consoles_properties() { // 콘솔을 준비하는 코드 } 공허하게 하다 consoles_preare() { // 콘솔이 없는 코드 } // ... 공허하게 하다 console_printNewLine() { 활자화하다("\n"); } 공허하게 하다 console_printString(마를 뜨다* 가치) { 활자화하다("%s", 가치); } 공허하게 하다 consoles_print정수(인트로 가치) { 활자화하다("%d", &가치); } 공허하게 하다 console_printBoolean(바가지 긁다 가치) { 활자화하다((가치) ? ("진짜") : ("거짓말")); } 공허하게 하다 console_scanNewLine() { 게걸스럽게 먹다(); } 공허하게 하다 console_scanString(마를 뜨다* 가치) { 스캔하다("%s", 가치); } 공허하게 하다 console_scanInteger(인트로* 가치) { 스캔하다("%d", 가치); } 공허하게 하다 콘솔_scanBoolean(바가지 긁다* 가치) { 마를 뜨다 임시 변통하다[512]; 스캔하다("%s", 임시 변통하다); *가치 = (발을 동동 구르다(온도, "진짜") == 0); } 실행
// 파일 이름: "messemo.c" #include <stdio.h> #include < 현악기>h> #include <ctype.h> #include <consoles.h> 공허하게 하다 orpelenemo_prepare() { consoles_properties(); } 공허하게 하다 위안드메모_unprepare() { consoles_preare(); } 인트로 orpelenemo_execute() { console_printString("헬로 월드"); console_printNewLine(); console_scanNewLine(); 돌아오다 0; } 인트로 본래의() { 오류코드 결과 = 0; orpelenemo_prepare(); 오류코드 = orpelenemo_execute(); 위안드메모_unprepare(); 돌아오다 오류코드; } 절차적 파스칼
이 예는 절차상 비모듈적 파스칼에 적용된다는 점에 유의한다.많은 파스칼 방언들은 "단위(s)"라고 불리는 네임스페이스 지원을 가지고 있다.일부 방언은 초기화 및 최종화를 지원하기도 한다.
네임스페이스가 지원되지 않는 경우 식별자 충돌을 방지하기 위해 모든 구성원 이름에 파일 이름 또는 모듈 이름과 관련된 접두사를 부여하는 것이 좋다.
정의
구성 단위 콘솔; (* 파일 이름: "filename.properties" *) 사용하다 크렛트; 절차 준비하다(); 시작되다 (* 콘솔을 준비하는 코드 *) 종지부를 찍다; 절차 꾸밈이 없는(); 시작되다 (* 콘솔이 없는 코드 *) 종지부를 찍다; // ... 절차 printNewLine(); 시작되다 WriteLn(); 종지부를 찍다; 절차 printString(가치: 끈을 매다); 시작되다 쓰다(가치); 종지부를 찍다; 절차 프린트인테거(가치: 정수의); 시작되다 쓰다(가치); 종지부를 찍다; 절차 printBoolean(가치: 부울); 시작되다 만일 (가치) 그때 시작되다 쓰다('진짜'); 종지부를 찍다 다른 시작되다 쓰다('거짓말'); 종지부를 찍다; 종지부를 찍다; 절차 scanNewLine(); 시작되다 구게이언(); 종지부를 찍다; 절차 스캔스트링(가치: 끈을 매다); 시작되다 ReadLn(가치); 종지부를 찍다; 절차 scanInteger(가치: 정수); 시작되다 ReadLn(가치); 종지부를 찍다; 절차 scanBoolean(가치: 부울); 시합을 하다 임시 변통하다: 끈을 매다; 시작되다 ReadLn(임시 변통하다); 만일 (온도 = '진짜') 그때 시작되다 가치 := 진실의; 종지부를 찍다 다른 시작되다 가치 := 거짓의; 종지부를 찍다; 종지부를 찍다; 실행
프로그램 위안이모; // 파일 이름: "properties.properties" 사용하다 콘솔; 절차 준비하다(); 시작되다 콘솔.준비하다(); 종지부를 찍다; 절차 꾸밈이 없는(); 시작되다 콘솔.꾸밈이 없는(); 종지부를 찍다; 기능을 발휘하다 처형하다(): 정수; 시작되다 콘솔.printString('헬로 월드'); 콘솔.printNewLine(); 콘솔.scanNewLine(); 처형하다 := 0; 종지부를 찍다; 시작되다 준비하다(); 처형하다(); 꾸밈이 없는(); 종지부를 찍다. 다른 개념과의 비교
네임스페이스
네임스페이스와 모듈 모두 단일 식별자에 의해 그리고 어떤 상황에서는 서로 교환하여 사용하는 여러 관련 실체를 그룹화할 수 있다.그러한 실체는 전 세계적으로 접근할 수 있다.두 개념의 주요 목적은 같다.
어떤 시나리오에서는 네임스페이스를 구성하는 글로벌 요소가 함수 또는 메서드 호출에 의해 초기화 및 마무리될 것을 요구한다.
많은 프로그래밍 언어에서 네임스페이스는 초기화 프로세스나 최종화 프로세스를 직접 지원하기 위한 것이 아니며, 따라서 모듈과 동등하지 않다.그 제한은 두 가지 방법으로 작용할 수 있다.글로벌 기능을 지원하는 네임스페이스에서는 초기화 함수와 최종화 함수가 직접 코딩되며, 메인 프로그램 코드로 직접 호출된다.
클래스 및 네임스페이스
클래스는 네임스페이스로 또는 네임스페이스와 함께 사용되기도 한다.네임스페이스를 지원하지 않지만(예: 자바스크립트) 클래스와 객체를 지원하는 프로그래밍 언어에서 클래스는 네임스페이스를 대체하기 위해 종종 사용된다.이러한 클래스는 일반적으로 인스턴스화되지 않으며 정적 멤버로만 구성된다.
싱글톤 클래스 및 네임스페이스
네임스페이스가 불완전하게 지원되는 객체 지향 프로그래밍 언어에서, 단일톤 패턴을 비인스턴스 클래스 내의 정적 멤버 대신 사용할 수 있다.
다른 설계 패턴과의 관계
모듈 패턴은 싱글톤 패턴의 전문화를 이용하여 구현할 수 있다.그러나 다른 설계 패턴을 같은 등급에 적용하고 결합할 수 있다.
이 패턴은 장식가, 플라이급 또는 어댑터로 사용될 수 있다.
설계 패턴으로서의 모듈
모듈 패턴은 크리에이티브 패턴과 구조 패턴으로 간주될 수 있다.다른 요소의 생성과 구성을 관리하고, 구조 패턴처럼 그룹화한다.
이 패턴을 적용하는 개체는 네임스페이스와 동등한 것을 제공할 수 있으며, 더 깨끗하고 간결한 구문 및 의미론을 가진 정적 클래스 또는 클래스의 초기화 및 최종화 프로세스를 제공할 수 있다.
그것은 클래스나 객체가 구조화된 절차적 데이터로 간주될 수 있는 특정한 경우를 지원한다.그리고, 반대로, 체계적이고 절차적인 데이터를 마이그레이션하고 객체 지향적인 것으로 간주한다.