2012-10-24 26 views
8

Tôi đang đọc sách "mẫu thiết kế javascript pro" và tìm thấy ít khó khăn trong việc hiểu mẫu "Giao diện" được đưa ra trong chương 2 vì không có mã hoàn chỉnh ví dụ minh họa việc sử dụng mẫu này.Ví dụ đang chạy hoặc bản trình diễn làm việc của mẫu Giao diện trong JavaScript

Tôi đang tìm kiếm một số giúp đỡ tìm hiểu mô hình này với một số chạy mã ví dụ có thể được trên jsfiddle, vv

Mô hình này được giải thích trong các trang sách 14-22, điểm chính tôi không hiểu là ở đâu và như thế nào Phương thức "addForm" được gọi. HOẶC nếu ai đó có thể hoàn thành ví dụ ResultFormatter với một số dữ liệu thử nghiệm và đối tượng, điều này thực sự sẽ rất hữu ích trong việc hiểu mẫu.

Mã cho cuốn sách "Pro Patterns Javascript Thiết kế" có thể được tải về từ http://jsdesignpatterns.com/ và đây là Chương 2.

Thanks for the help !!

+0

Điều gì khiến bạn bối rối? Bạn có thể nhận được phản hồi tốt hơn khi đặt câu hỏi cụ thể hơn. –

+2

Tôi thấy rất khó để tìm thấy một thực hiện thực tế này, chủ yếu là làm thế nào để sử dụng nó. Chỉ cần tìm kiếm một mã thực hiện mẫu này. Cảm ơn bạn đã xem xét truy vấn này !! –

+0

@AnmolSaraf Tôi đã thêm vào thực thi es6 cùng mã, vui lòng tham khảo nó. Cú pháp đơn giản hơn để hiểu nếu bạn đến từ nền OOP. –

Trả lời

8

Tôi đã thấy mô hình thực hiện theo những cách khác nhau, nhưng ý tưởng rất đơn giản:

  1. Bạn có một số lớp - giao diện của bạn - mà chỉ đơn giản xác định tên của một số chức năng. (Bạn có thể muốn có một lớp được gọi là Giao diện mà các giao diện thực của bạn khởi tạo, do đó giao diện của bạn có kiểu Giao diện)
  2. Sau đó, bạn có một số lớp khác triển khai giao diện đó. Điều này có nghĩa rằng lớp thứ hai này phải có ít nhất tất cả các chức năng được chỉ định bởi giao diện.
  3. Cuối cùng, bạn có một số chức năng khác ở một nơi khác, hy vọng sẽ nhận được một đối tượng thực hiện giao diện. Trong mã mẫu mà bạn đề cập, hàm này là addForm, hàm này hy vọng một đối tượng thực hiện các giao diện 'Composite' và 'FormItem'.
  4. Hàm này sau đó lặp qua tất cả các phương thức của (các) giao diện mà nó mong đợi và kiểm tra xem đối tượng bạn đã truyền vào nó cũng có các phương thức đó hay không. Nếu một phương thức từ một trong các giao diện không được tìm thấy trong đối tượng được truyền vào hàm, nó xác định đối tượng đó không thực hiện giao diện và ném một ngoại lệ.

Một số người có thể thấy mô hình này không thực tế vì chi phí liên quan, nhưng do thiếu hỗ trợ gốc cho giao diện của Javascript, đây không phải là giải pháp quá tệ. Một số người cũng có thể thấy rằng việc sử dụng giao diện cho các dự án nhỏ trong Javascript là quá mức cần thiết.

Ví dụ

var Interface = function(name, methods) { 
    this.name = name; 
    this.methods = []; 

    if (methods.constructor == Array) 
     this.methods = methods; 
    else if (methods.constructor == String) 
     this.methods[0] = methods; 
    else 
     throw new Error("Interface must define methods as a String or an Array of Strings"); 
}; 

var InterfaceHelper = { 
    ensureImplements : function(obj, interfaces) { 
     // If interfaces is not an array, assume it's a function pointer 
     var toImplement = interfaces.constructor == Array ? interfaces : [interfaces]; 
     var interface; 

     // For every interface that obj must implement: 
     for (var i = 0, len = toImplement.length; i < len; i++) { 
      interface = toImplement[i]; 

      // Make sure it indeed is an interface 
      if (interface.constructor != Interface) 
      throw new Error("Object trying to implement a non-interface. " 
      + interface.name + " is not an Interface."); 

      // Make sure obj has all of the methods described in the interface 
      for (var j = 0, interfaceLen = interface.methods.length; j < interfaceLen; j++) 
      if (!obj[interface.methods[j]]) 
       throw new Error("Interface method not implemented. " 
       + interface.name + " defines method " + interface.methods[j]); 
     } 

     return true; 
    } 
}; 

var Drawable = new Interface("Drawable", ["onDraw"]); 

var Surface = function() { 
    this.implements = ["Drawable"]; 

    this.onDraw = function() { 
     console.log("Surface Drawing"); 
    }; 
}; 

Cách sử dụng

var myDrawableSurface = new Surface(); 

// Returns true 
InterfaceHelper.ensureImplements(myDrawableSurface, Drawable); 

// Returns false (Error thrown) 
InterfaceHelper.ensureImplements(myDrawableSurface, Array); 
4

Completed ví dụ cuốn sách và đây là làm việc jsfiddle, -

var Interface = function(name, methods) { 
    if (arguments.length != 2) { 
     throw new Error("Interface constructor called with " + arguments.length + "arguments, but expected exactly 2."); 
    } 

    this.name = name; 
    this.methods = []; 

    for (var i = 0, len = methods.length; i < len; i++) { 
     if (typeof methods[i] !== 'string') { 
      throw new Error("Interface constructor expects method names to be " + "passed in as a string."); 
     } 

     this.methods.push(methods[i]); 
    } 
}; 

// Static class method. 
Interface.ensureImplements = function(object) { 
    if (arguments.length < 2) { 
     throw new Error("Function Interface.ensureImplements called with " + arguments.length + "arguments, but expected at least 2."); 
    } 

    for (var i = 1, len = arguments.length; i < len; i++) { 
     var interface = arguments[i]; 

     if (interface.constructor !== Interface) { 
      throw new Error("Function Interface.ensureImplements expects arguments" + "two and above to be instances of Interface."); 
     } 

     for (var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) { 
      var method = interface.methods[j]; 

      if (!object[method] || typeof object[method] !== 'function') { 
       throw new Error("Function Interface.ensureImplements: object " + "does not implement the " + interface.name + " interface. Method " + method + " was not found."); 
      } 
     } 
    } 
}; 

function Map() {} 

Map.prototype.centerOnPoint = function(x,y) { 
    alert('center=> x: ' + x + ', y: ' + y); 
}; 

Map.prototype.zoom = function(x){ 
    alert('zoom : ' + x); 
} 

Map.prototype.draw = function(){ 
    alert('draw'); 
}; 

var map = new Map(); 
var DynamicMap = new Interface('DynamicMap', ['centerOnPoint', 'zoom', 'draw']); 

function displayRoute(mapInstance) { 
    Interface.ensureImplements(mapInstance, DynamicMap); 
    mapInstance.centerOnPoint(12, 34); 
    mapInstance.zoom(5); 
    mapInstance.draw(); 
} 

displayRoute(map);​ 
0

ES6 đã thêm syntacti cal đường cho ngôn ngữ. Dưới đây là triển khai ES6 của cùng một ví dụ.

class Interface { 
 
    constructor(name, methods) { 
 
     if (arguments.length < 2) { 
 
      throw new Error('An Interface expects atleast 2 arguments ' + arguments.length 
 
       + ' arguments passed') 
 
      
 
     } 
 
     this.name = name 
 
     this.methods = [] 
 
     methods.forEach(method => { 
 
      if (typeof method !== 'string') { 
 
       throw new Error('Interface expects all the method names to be passed as as a string ' + 
 
        method + ' is a ' + typeof method) 
 
      } 
 
      this.methods.push(method) 
 
     }, this); 
 
    } 
 

 
    static ensureImplements(object) { 
 
     if(arguments.length < 2) { 
 
      throw new Error("Function Interface.ensureImplements called with " + 
 
       arguments.length + "arguments, but expected at least 2.") 
 
     } 
 

 
     for (let i = 1, len=arguments.length; i < len; i++) { 
 
      const interf = arguments[i] 
 
      if(interf.constructor !== Interface) { 
 
       throw new Error('Function expects arguments two or above to be instaces of Interface') 
 
      } 
 

 
      for(let j = 0, methodsLen = interf.methods.length; j < methodsLen; j++) { 
 
       const method = interf.methods[j] 
 
       if(!object[method] || !typeof object[method] === 'function') { 
 
        throw new Error('Does not implement the method the interface' + interf.name + 'Interface.Method ' 
 
        + method + ' not found') 
 
       } 
 
      } 
 
     } 
 
    } 
 
} 
 

 
const DynamicMap = new Interface('DynamicMap', ['centerOnPoint', 'zoom', 'draw']) 
 

 
class Map { 
 
    constructor() { 
 
     Interface.ensureImplements(this, DynamicMap) 
 
    } 
 
    centerOnPoint() { 
 
     console.log('Moving to center') 
 
    } 
 
    zoom() { 
 
     console.log('Zooming in') 
 
    } 
 

 
    draw() { 
 
     console.log('Drawing map') 
 
    } 
 
} 
 

 
const mapInstance = new Map()

Hãy thử chơi xung quanh với mã bằng cách loại bỏ các phương pháp trong lớp Map. Hy vọng nó giải thích tốt hơn cho những người đến từ nền oops

Các vấn đề liên quan