The Singleton Pattern

싱글톤 패턴은 클래스의 인스턴스화를 하나 객체로 제한하는 것으로 알려져 있습니다. 관행적으로 싱글톤 패턴은 객체에 대한 인스턴스가 하나 존재하지 않을 경우에만 객체를 생성하도록 만드는 메소드를 구현해서 생성할 수 있습니다. 인스턴스가 이미 존재하는 경우에는 해당 객체에 대한 참조 만 반환합니다.

싱글톤은 정적 클래스 (또는 객체)와는 다르게 초기화를 지연시킬 수 있고, 일반적으로 초기화 하는 동안 사용할 수 없는 정보가 필요합니다. 싱글톤은 쉽게 검색하기 위해 이전 참조를 인식하지 못하는 코드를 제공하지 않습니다. 이것은 싱글톤에 의해 반환 된 것은 객체 또는 "클래스"가 아니고 구조이기 때문 입니다. 클로저 변수가 실제로 클로저가 아닌 방법을 생각해보십시오. 클로저를 제공하는 함수 범위는 클로저입니다.

JavaScript에서 싱글톤은 전역 네임 스페이스에서 구현 코드를 격리하여 함수에 대한 단일 액세스 지점을 제공하는 공유 리소스 네임 스페이스 역할을합니다.

다음과 같이 Singleton을 구현할 수 있습니다.

var mySingleton = (function () {

  // Instance stores a reference to the Singleton
  var instance;

  function init() {

    // Singleton

    // Private methods and variables
    function privateMethod(){
        console.log( "I am private" );
    }

    var privateVariable = "Im also private";

    var privateRandomNumber = Math.random();

    return {

      // Public methods and variables
      publicMethod: function () {
        console.log( "The public can see me!" );
      },

      publicProperty: "I am also public",

      getRandomNumber: function() {
        return privateRandomNumber;
      }

    };

  };

  return {

    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: function () {

      if ( !instance ) {
        instance = init();
      }

      return instance;
    }

  };

})();

var myBadSingleton = (function () {

  // Instance stores a reference to the Singleton
  var instance;

  function init() {

    // Singleton

    var privateRandomNumber = Math.random();

    return {

      getRandomNumber: function() {
        return privateRandomNumber;
      }

    };

  };

  return {

    // Always create a new Singleton instance
    getInstance: function () {

      instance = init();

      return instance;
    }

  };

})();


// Usage:

var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); // true

var badSingleA = myBadSingleton.getInstance();
var badSingleB = myBadSingleton.getInstance();
console.log( badSingleA.getRandomNumber() !== badSingleB.getRandomNumber() ); // true

// Note: as we are working with random numbers, there is a
// mathematical possibility both numbers will be the same,
// however unlikely. The above example should otherwise still
// be valid.

싱글 톤을 만드는 이유는 (적어도 정적 언어에서는) new MySingleton()을 직접 호출하지 않고 MySingleton.getInstance()를 통해 인스턴스를 전역 액세스 하기 위해서 입니다. 이것은 JavaScript에서 가능합니다.

GoF 서적에서 Singleton 패턴은 다음과 같이 설명됩니다.

  • 정확히 하나의 클래스 인스턴스가 있어야 하며 클라이언트가 잘 알려진 액세스 포인트를 통해 액세스 할 수 있어야합니다.
  • 단독 인스턴스가 서브 클래싱을 통해 확장 가능해야하고 클라이언트가 코드를 수정하지 않고 확장된 인스턴스를 사용할 수 있어야합니다.

이 두 번째 점은 다음과 같은 코드가 필요한 경우를 나타냅니다.

mySingleton.getInstance = function(){
  if ( this._instance == null ) {
    if ( isFoo() ) {
       this._instance = new FooSingleton();
    } else {
       this._instance = new BasicSingleton();
    }
  }
  return this._instance;
};

여기서 getInstance는 Factory 메소드와 조금 비슷해지며 코드에 액세스 할 때마다 각 포인트를 업데이트 할 필요가 없습니다. 위의 FooSingletonBasicSingleton의 하위 클래스이며 동일한 인터페이스를 구현합니다.

Singleton에서 실행을 지연시키는 것이 중요한 이유는 무엇입니까?

C ++에서는 동적 초기화 순서의 예측 불가능성을 차단하여 프로그래머에게 제어권을 반환합니다.

클래스 정적 객체의 인스턴스와 싱글톤의 차이점을 알아 두는 것이 중요합니다. 싱글톤은 정적 인스턴스로 구현 될 수 있지만 실제 필요할 때까지 리소스 또는 메모리가 필요하지 않습니다.

만약 우기에게 직접 초기화 할 수 있는 정적 객체가 있는 경우, 항상 동일한 순서로 코드가 실행되도록 해야하고 (예 : objCar의 초기화 중에 objWheel이 필요한 경우) 많은 소스파일이 있는 경우 크기가 조정되지 않습니다.

싱글 톤과 정적 객체 모두 유용하지만 남용하지 않아야합니다. 다른 패턴을 과도하게 사용해서는 안됩니다.

실제로 Singleton 패턴은 시스템에서 다른 객체를 조정하는 데 정확히 하나의 객체가 필요할 때 유용합니다. 다음은 이 컨텍스트에서 사용되는 패턴의 예입니다.

var SingletonTester = (function () {

  // options: an object containing configuration options for the singleton
  // e.g var options = { name: "test", pointX: 5};
  function Singleton( options ) {

    // set options to the options supplied
    // or an empty object if none are provided
    options = options || {};

    // set some properties for our singleton
    this.name = "SingletonTester";

    this.pointX = options.pointX || 6;

    this.pointY = options.pointY || 10;

  }

  // our instance holder
  var instance;

  // an emulation of static variables and methods
  var _static = {

    name: "SingletonTester",

    // Method for getting an instance. It returns
    // a singleton instance of a singleton object
    getInstance: function( options ) {
      if( instance === undefined ) {
        instance = new Singleton( options );
      }

      return instance;

    }
  };

  return _static;

})();

var singletonTest = SingletonTester.getInstance({
  pointX: 5
});

// Log the output of pointX just to verify it is correct
// Outputs: 5
console.log( singletonTest.pointX );

싱글톤은 유효한 사용법을 가지고 있지만 JavaScript에서 필요로 할 때 종종 디자인을 재평가 해야 합니다.

종종 시스템의 모듈이 단단히 연결되어 있거나 논리가 코드베이스의 여러 부분에 지나치게 분산되어 있음을 나타냅니다. 싱글 톤은 숨겨진 의존성, 다중 인스턴스 생성의 어려움, 종속성을 스터빙하는 데 어려움이 있으므로 문제를 테스트하기가 더 어려울 수 있습니다.

Miller Medeiros는 이전에 Singleton이 어떻게 의존성을 단단하게 만들 수 있는지에 대해 논의하면서 이 기사에 대한 설명과 추가 독서를 위한 Singleton 및 다양한 문제에 대해 이 우수한 기사를 추천했습니다. 두 작품 모두 주목할 가치가 있고 이 패턴에 대한 많은 중요한 점을 제기 했지만 두 번째 기사를 추천합니다.

results matching ""

    No results matching ""