2012-10-24 7 views
8

Sto leggendo il libro "pro javascript design patterns" e trovo poche difficoltà nel comprendere il pattern "Interface" fornito nel libro capitolo 2 in quanto non c'è un codice completo esempio che dimostra l'uso di questo modello.Un esempio in esecuzione o demo funzionante di Pattern di interfaccia in JavaScript

Sto cercando qualche aiuto comprensione di questo modello con un po 'esempio di codice in esecuzione può essere su jsfiddle ecc

Questo modello è spiegato nelle pagine del libro 14-22, punto principale non sto comprensione è dove e come Viene chiamato il metodo "addForm". O se qualcuno può completare l'esempio ResultFormatter con alcuni dati di test e oggetto questo sarà davvero molto utile per capire il modello.

Codice per il libro "Pro Patterns Javascript design" può essere scaricato da http://jsdesignpatterns.com/ e questo è Capitolo 2.

Grazie per l'aiuto !!

+0

Che cosa ti confonde? Potresti ottenere una risposta migliore ponendo una domanda più specifica. –

+2

Mi risulta difficile trovare una implementazione pratica di questo, principalmente come usarlo. Sto solo cercando un codice che implementa questo modello. Grazie per aver esaminato questa query !! –

+0

@AnmolSaraf Ho aggiunto l'implementazione es6 dello stesso codice, fare riferimento ad esso. La sintassi è più semplice da capire se sei di origine OOP. –

risposta

8

ho visto il modello implementato in modi diversi, ma l'idea è semplice:

  1. Hai qualche classe - l'interfaccia - che specifica semplicemente i nomi di alcune funzioni. (Si potrebbe desiderare di avere una classe chiamata Interfaccia che le vostre interfacce reali istanziano, solo così le vostre interfacce sono di tipo Interfaccia)
  2. Avete quindi qualche altra classe che implementa tale interfaccia. Ciò significa che questa seconda classe deve avere almeno tutte le funzioni specificate dall'interfaccia.
  3. Infine, avete qualche altra funzione da qualche altra parte, che si aspetta di ricevere un oggetto che implementa l'interfaccia. Nel codice di esempio che hai citato, questa funzione è addForm, che si aspetta un oggetto che implementa le interfacce "Composite" e "FormItem".
  4. Questa funzione esegue quindi il ciclo di tutti i metodi delle interfacce che si aspetta e verifica che anche l'oggetto a cui è passato abbia quei metodi. Se un metodo da una delle interfacce non viene trovato nell'oggetto passato alla funzione, determina che l'oggetto non implementa l'interfaccia e genera un'eccezione.

Alcune persone possono trovare questo modello non pratico a causa del sovraccarico, ma data la mancanza di supporto nativo per le interfacce di Javascript, questa soluzione non è male. Alcune persone potrebbero anche scoprire che l'uso di interfacce per piccoli progetti in Javascript è eccessivo.

Esempio

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"); 
    }; 
}; 

Uso

var myDrawableSurface = new Surface(); 

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

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

Completato l'esempio libro e qui è il lavoro jsfiddle, -

syntacti
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 ha aggiunto zucchero cal alla lingua. Di seguito è l'implementazione ES6 dello stesso esempio.

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()

Prova a giocare con il codice, eliminando i metodi della classe Map. Spero che spieghi meglio alle persone che provengono da oops background

Problemi correlati