본문 바로가기

Javascript

Revealing Module Pattern

http://weblogs.asp.net/dwahlin/archive/2011/08/02/techniques-strategies-and-patterns-for-structuring-javascript-code-revealing-module-pattern.aspx
이 글은 위의 기사를 번역 한 글입니다. 조금 내용과 상이 할수 있습니다.


Revealing Module Pattern
 은  Module Pattern에 근간을 두고 있습니다. 장점은 보다 쉽게 코드를 이해할수 있고 보다 구조적으로 구성할수 있습니다.  이 패턴의 시작은 아래와 같이 함수를 변수로 정의하고 그 다음 자바스크립트가 로드될때 바로 그 함수를 호출합니다. 마지막 ()가로가 함수를 호출하는 부분입니다.
var Calculator = function () { /* Code goes here */ }();

Calculator object안에 캡슐화된 변수화 함수들은 위의 Code goes here부분에 들어가게 됩니다.
이 패턴의 좋은 점은 어떤 멤버는 private이고 어떤 member는 public인지 접근을 제한할 수 있습니다.
public 멤버로 선언하기 위해서는 함수 마지막에 return 구문을 삽입함으로써 구현할수 있습니다. 
다음코드는 Revealing Module Pattern에 대한 코드입니다.

 

var Calculator = function () {
    var eqCtl,
    currNumberCtl,
    operator,
    operatorSet = false,
    equalsPressed = false,
    lastNumber = null,

    init = function (equals, currNumber) {
        eqCtl = equals;
        currNumberCtl = currNumber;
    },

    add = function (x, y) {
        return x + y;
    },

    subtract = function (x, y) {
        return x - y;
    },

    multiply = function (x, y) {
        return x * y;
    },

    divide = function (x, y) {
        if (y == 0) {
            alert("Can't divide by 0");
            return 0;
        }
        return x / y;
    },

    setVal = function (val) {
        currNumberCtl.innerHTML = val;
    },

    setEquation = function(val) {
        eqCtl.innerHTML = val;
    },

    clearNumbers = function() {
        lastNumber = null;
        equalsPressed = operatorSet = false;
        setVal('0');
        setEquation('');
    },

    setOperator = function(newOperator) {
        if (newOperator == '=') {
            equalsPressed = true;
            calculate();
            setEquation('');
            return;
        }

        //Handle case where = was pressed
        //followed by an operator (+, -, *, /)
        if (!equalsPressed) calculate();
        equalsPressed = false;
        operator = newOperator;
        operatorSet = true;
        lastNumber = parseFloat(currNumberCtl.innerHTML);
        var eqText = (eqCtl.innerHTML == '') ?
            lastNumber + ' ' + operator + ' ' :
            eqCtl.innerHTML + ' ' + operator + ' ';
        setEquation(eqText);
    },

    numberClick = function(e) {
        var button = (e.target) ? e.target : e.srcElement;
        if (operatorSet == true || currNumberCtl.innerHTML == '0') {
            setVal('');
            operatorSet = false;
        }
        setVal(currNumberCtl.innerHTML + button.innerHTML);
        setEquation(eqCtl.innerHTML + button.innerHTML);
    },

    calculate = function() {
        if (!operator || lastNumber == null) return;
        var currNumber = parseFloat(currNumberCtl.innerHTML),
            newVal = 0;
        //eval() would've made this a whole lot simpler
        //but didn't want to use it in favor of a more
        //"robust" set of methods to demo patterns
        switch (operator) {
        case '+':
            newVal = add(lastNumber, currNumber);
            break;
        case '-':
            newVal = subtract(lastNumber, currNumber);
            break;
        case '*':
            newVal = multiply(lastNumber, currNumber);
            break;
        case '/':
            newVal = divide(lastNumber, currNumber);
            break;
        }
        setVal(newVal);
        lastNumber = newVal;
    };

    return {
        init: init,
        numberClick: numberClick,
        setOperator: setOperator,
        clearNumbers: clearNumbers
    };
} ();
 
public으로 노출되어야 하는 함수는 Calculator object에 return섹션에 정의되어야합니다.
간단하게 Javascript Object문자로 정의된 함수들은 (init, numberClick, setOperator ,clearNumbers) 은 main Calculator함수가 호출될때 리턴됩니다. 그리고 다른 모든 변수와 함수들은 private이 됩니다.
자바스크립트는 C#이나 JAVA처럼 접근제한자를 지원하지 않습니다. 그러나 이 패턴은 이러한 기능을 제공합니다.

위의 코드를 보면 아시겠지만 전 예제 와는 다르게 init함수가 추가 되었습니다. 이 함수의 역할은 Calculator Object가 필요로 하는 데이터르르 초기화 시켜주기위한 함수입니다. 위의 패턴을 사용할때
아래와 같이 함수 초기화가 필요합니다.

window.onload = function () {
    var eqCtl = document.getElementById('Equation');            
    var currNumberCtl = document.getElementById('CurrentNumber');
    Calculator.init(eqCtl, currNumberCtl);
};