Những mẫu thiết kế mã javaScript: Singleton pattern

  • JavaScript
  • 23 tháng 12 2013
  • bởi Văn Khương
  • 0 Comments

Mẫu Singleton được biết đến nhiều trong các ngôn ngữ lập trình hướng đối tượng, nếu bạn đã có kinh nghiệm ở một ngôn ngữ lập trình hướng đối tượng phổ biến nào đó chắc sẽ không còn xa lạ, chúng ta sẽ thấy một số framework họ luôn muốn dùng một phương thức để dùng khởi tạo đối tượng như getInstance(). Cũng như các ngôn ngữ khác mục đích chính của mẫu này là nhắm tránh việc chạy đi chạy lại một thứ gì đó khi khởi tạo đối tượng nhiều lần. Bằng việc sử dụng 1 phương thức để khởi tạo thường được đặt tên là getInstance(). Ví dụ:

var mySingleton = (function () {
  var instance;
  function init() {
    // Private
    var privateRandomNumber = Math.random();
    return {
       // Public
       getRandomNumber: function() {
          return privateRandomNumber;
       }
    };
  }
  return {
    getInstance: function () {
       if ( !instance ) instance = init();
       return instance;
    }
  };
})();
var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log(singleA.getRandomNumber());
console.log(singleB.getRandomNumber());

Kết quả ở trên cho thấy khi bạn khởi tạo đối tượng bằng phương thức getInstance() thì hàm init() chỉ chạy lần đầu những lần sau biến instance đã lưu trữ thông tin nên chỉ việc trả về, nếu chúng ta bỏ câu điều kiện if(!instance) thì kết quả sẽ khác. Điều này là có ích khi bạn muốn những chức năng cài đặt được chạy duy nhất lần đầu, thực hiện được điều này ta đã góp phần tối ưu được ứng dụng, nhưng nó cần được thực hiện ở một mục đích cụ thể khi cần thiết nhằm tránh lạm dụng. Với cách viết trên thì chúng ta cũng bắt buộc phải khởi tạo đối tượng bằng phương thức getInstance() bạn không được gọi trực tiếp chẳng hạn như new MySingleton(). Mẫu Singletons còn được sử dụng trong constructor, cũng với cách hiểu như trên chúng ta cũng sử dụng một biến để lưu thông tin đối tượng tạm gọi là instance. Ví dụ:

function Singleton() {
   if (typeof Singleton.instance === 'object') {
      return Singleton.instance;
   }
   var randomNumber = Math.random();
   this.testNumber = function(){
      console.log(randomNumber);
   };
   // cache
   Singleton.instance = this;
}
var user = new Singleton();
var person = new Singleton();
user.testNumber();
person.testNumber();

Kết quả ví dụ trên khẳng định rằng các biến instance đã có tác dụng trong việc lưu thông tin đối tượng và những lần khởi tạo đối tượng tiếp theo nó chỉ trả về. Chúng ta có thể kiểm tra biến instance phía cuối bằng cách gom những thứ cần thực hiện trong một hàm nhưng việc kiểm tra ngay ở phía trên là tối ưu hơn. Trong constructor chúng ta cũng có thể trả về một đối tượng, điều này có nghĩa những thông tin trong đối tượng đó sẽ có tính chất là public còn những thứ còn lại trong constructor sẽ có tính chất là private (sử dụng từ khóa var để có phạm vi trong hàm), lúc này để áp dụng tinh thần của mẫu Singleton chúng ta sẽ kiểm tra đối tượng để quyết định trả về luôn cho những lần gọi tiếp theo. Ví dụ:

function Singleton(){
  if(Singleton.instance !== undefined)
     return Singleton.instance;
  var privateMumber = Math.random();
  // All public methods
  Singleton.instance = {
     getMumber: function(){
        return privateMumber;
     }
  };
  return Singleton.instance;
}
s = new Singleton();
s2 = new Singleton();
console.log(s.getMumber());
console.log(s2.getMumber());

Chúng ta có thể thấy mẫu có Singleton cũng có nhiều cách thức viết khác nhau nhưng ý nghĩa chung thì không thay đổi, tùy theo cách sử dụng đối tượng trong javaScript của bạn và mục đích của bạn để quyết định có nên dùng mẫu Singleton hay không và dùng như thế nào. Nếu sử dụng tốt ứng dụng của bạn sẽ khá tối ưu.

Tham khảo: addyosmani.com, bumbu.ru

  • Chia sẻ
comments powered by Disqus