The Facade Pattern

우리가 정면을 세울 때, 우리는 아주 다른 현실을 숨길 수있는 세상에 외모를 나타냅니다. 이것은 우리가 검토 할 다음 패턴 인 Facade 패턴의 이름에 영감을주었습니다. 이 패턴은 더 큰 코드 본문에 편리한 상위 인터페이스를 제공하여 진정한 기본 복잡성을 숨 깁니다. 다른 개발자에게 제공되는 API를 단순화하는 것으로 생각하면 거의 항상 유용성이 향상됩니다.

Facades는 jQuery와 같은 JavaScript 라이브러리에서 흔히 볼 수있는 구조적 패턴입니다. 구현이 광범위한 동작을 가진 메소드를 지원할 수 있지만이 메소드의 "외관"또는 제한된 추상화 만이 대중에게 사용되어 제공됩니다.

이를 통해 우리는 배경의 하위 시스템이 아닌 Facade와 직접 상호 작용할 수 있습니다. jQuery의 $(el).css() 또는 $(el).animate() 메소드를 사용할 때마다 우리는 실제로 Facade를 사용하고 있습니다. jQuery 코어에서 수동으로 많은 내부 메소드를 호출하지 않아도되는 더 단순한 공용 인터페이스 어떤 행동을하기 위해서. 또한 DOM API와 수동으로 상호 작용하고 상태 변수를 유지할 필요가 없습니다.

jQuery 핵심 메소드는 중간 추상화로 간주되어야한다. 개발자들에게 즉각적인 부담이되는 것은 DOM API이며 facades는 jQuery 라이브러리를 매우 쉽게 사용할 수있게합니다.

우리가 배운 것에 기반하여 Facade 패턴은 클래스의 인터페이스를 단순화하고 클래스를 활용하는 코드와 클래스를 분리합니다. 이는 서브 시스템에 직접 액세스하는 것보다 때때로 오류가 덜 발생하는 방식으로 서브 시스템과 간접적으로 상호 작용하는 기능을 제공합니다. Facade의 장점으로는 사용 편의성과 패턴 구현시 작은 크기의 공간이 포함되는 경우가 있습니다.

작동중인 패턴을 살펴 보겠습니다. 이것은 최적화되지 않은 코드 예제이지만 Facade를 사용하여 브라우저 간 이벤트를 수신하기위한 인터페이스를 단순화합니다. 우리는 안전하고 크로스 - 브라우저 호환 솔루션을 제공 할 수 있도록 기능의 존재를 확인하는 작업을 수행하는 코드에서 사용할 수있는 공통 방법을 작성하여이 작업을 수행합니다.

var addMyEvent = function( el,ev,fn ){

   if( el.addEventListener ){
            el.addEventListener( ev,fn, false );
      }else if(el.attachEvent){
            el.attachEvent( "on" + ev, fn );
      } else{
           el["on" + ev] = fn;
    }

};

유사한 방식으로 우리는 모두 jQuery의 $(document).ready(..)에 익숙합니다. 내부적으로 이것은 실제로 bindReady()라는 메소드에 의해 구동되는데,이 작업은 다음을 수행합니다.

bindReady: function() {
    ...
    if ( document.addEventListener ) {
      // Use the handy event callback
      document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

      // A fallback to window.onload, that will always work
      window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {

      document.attachEvent( "onreadystatechange", DOMContentLoaded );

      // A fallback to window.onload, that will always work
      window.attachEvent( "onload", jQuery.ready );
               ...

이것은 세계의 나머지 부분이 $(document).ready(..)에 의해 노출 된 제한된 인터페이스를 단순히 사용하는 Facade의 또 다른 예이며보다 복잡한 구현은 시각적으로 숨겨진 상태로 유지됩니다.

Facades는 단지 독자적으로 사용되어서는 안됩니다. 모듈 패턴과 같은 다른 패턴과 통합 될 수도 있습니다. 아래에서 볼 수 있듯이 모듈 패턴의 인스턴스에는 비공개로 정의 된 여러 메소드가 포함되어 있습니다. Facade는 다음 메소드에 액세스하는 훨씬 간단한 API를 제공하는 데 사용됩니다.

var module = (function() {

    var _private = {
        i: 5,
        get: function() {
            console.log( "current value:" + this.i);
        },
        set: function( val ) {
            this.i = val;
        },
        run: function() {
            console.log( "running" );
        },
        jump: function(){
            console.log( "jumping" );
        }
    };

    return {

        facade: function( args ) {
            _private.set(args.val);
            _private.get();
            if ( args.run ) {
                _private.run();
            }
        }
    };
}());


// Outputs: "current value: 10" and "running"
module.facade( {run: true, val: 10} );

이 예제에서 module.facade()를 호출하면 실제로 모듈 내에서 일련의 비공개 동작이 트리거되지만 다시 사용자는이 문제에 관심을 갖지 않습니다. 우리는 구현 레벨 세부 사항에 대해 걱정할 필요없이 기능을 사용하는 것이 훨씬 쉬워졌습니다.

추상화에 대한 참고 사항

Facades에는 일반적으로 몇 가지 단점이 있지만 주목할 가치가있는 사항은 성능입니다. 즉, 퍼스펙티브가 구현에 제공 한 추상화에 대한 암시 적 비용이 있는지 여부와 이러한 비용이 정당한 지 여부를 결정해야합니다. jQuery 라이브러리로 돌아가서 우리 대부분은 getElementById("identifier")$("#identifier")를 사용하여 페이지의 요소를 ID로 쿼리 할 수 ​​있음을 알고있다.

그러나 getElementById()는 자체적으로 더 높은 수준으로 훨씬 빠릅니다. 이 jsPerf 테스트를 통해 브라우저 별 결과를 확인하십시오 : http://jsperf.com/getelementbyid-vs-jquery-id. 물론 jQuery (및 Sizzle - 선택기 엔진)는 쿼리를 최적화하기 위해 훨씬 더 많은 작업을 수행하고 있습니다 (그리고 DOM 노드가 반환되는 것이 아니라 jQuery 객체).

이 특정 Facade의 문제점은 여러 유형의 쿼리를 수락하고 파싱 할 수있는 우아한 선택기 기능을 제공하기 위해 암시적인 추상화 비용이 있다는 것입니다. 사용자는 jQuery.getById("identifier") 또는 jQuery.getByClass("identifier") 등을 액세스 할 필요가 없습니다. 즉, 성능에 대한 절충안은 실제로 수년에 걸쳐 실제로 테스트되었으며 jQuery의 성공을 감안할 때 단순한 Facade가 팀에서 실제로 잘 수행되었습니다.

패턴을 사용할 때 관련된 성능 비용을 인식하고 제공되는 추상화 수준에 부합하는지 여부를 확인하십시오.

results matching ""

    No results matching ""