2012-10-24 9 views
8

Czytam książkę "pro javascript design patterns" i trudno mi zrozumieć wzór "interfejsu" podany w rozdziale 2 książki, ponieważ nie ma pełnego kodu przykład demonstrujący użycie tego wzoru.Bieżący przykład lub działająca demonstracja wzorca interfejsu w kodzie JavaScript

szukam jakiejś pomocy zrozumienie tego wzoru z jakimś systemem przykład kodu może być na jsfiddle itp

Ten wzór jest wyjaśniony w książce stronach 14 - 22, głównym punktem nie mam zrozumienia, gdzie i jak Wywoływana jest metoda "addForm". LUB , jeśli ktoś może wypełnić przykład ResultFormatter z niektórymi danymi testowymi i obiektem, będzie to bardzo pomocne w zrozumieniu wzorca.

Kod książki „Pro JavaScript Wzorce projektowe” można pobrać ze http://jsdesignpatterns.com/ i to jest Rozdział 2.

Dzięki za pomoc !!

+0

Co Cię martwi? Możesz uzyskać lepszą odpowiedź, zadając bardziej szczegółowe pytanie. –

+2

Mam trudności ze znalezieniem praktycznej realizacji tego, głównie z tego, jak z niego korzystać. Po prostu szukam kodu, który implementuje ten wzorzec. Dzięki za zaglądanie w to zapytanie !! –

+0

@AnmolSaraf Dodałem implementację es6 tego samego kodu, zapoznaj się z nim. Składnia jest łatwiejsza do zrozumienia, jeśli pochodzisz z tła OOP. –

Odpowiedz

8

Widziałem wzór realizowane na różne sposoby, ale idea jest prosta:

  1. Masz jakąś klasę - interfejs - to po prostu Określa nazwy niektórych funkcji. (Możesz chcieć mieć klasę o nazwie Interface, którą Twoi rzeczywiste interfejsy tworzą, tak, żeby twoje interfejsy były typu Interface).
  2. Następnie masz inną klasę, która implementuje taki interfejs. Oznacza to, że ta druga klasa musi mieć co najmniej wszystkie funkcje określone przez interfejs.
  3. Wreszcie, masz inną funkcję gdzieś indziej, która oczekuje na otrzymanie obiektu implementującego interfejs. W przykładowym kodzie, o którym wspomniałeś, ta funkcja to addForm, która oczekuje obiektu implementującego interfejs "Composite" i "FormItem".
  4. Ta funkcja następnie przeplata wszystkie metody interfejsu (ów), których oczekuje, i sprawdza, czy obiekt, który do niego przekazałeś, również posiada te metody. Jeśli nie znaleziono metody z jednego z interfejsów w obiekcie przekazanym do funkcji, oznacza to, że obiekt nie implementuje interfejsu i zgłasza wyjątek.

Niektóre osoby mogą uznać ten wzór za niepraktyczny ze względu na związane z nim koszty, ale biorąc pod uwagę brak naturalnej obsługi interfejsów przez Javascript, nie jest to zbyt złe rozwiązanie. Niektóre osoby mogą również stwierdzić, że używanie interfejsów dla małych projektów w JavaScript jest przesadzone.

Przykład

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

Zastosowanie

var myDrawableSurface = new Surface(); 

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

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

Zakończono przykład książka i jest tu pracy 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 dodano syntacti Cal cukru na język. Poniżej znajduje się implementacja ES6 tego samego przykładu.

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

Spróbuj zabawy z kodu poprzez usunięcie metod w klasie Map. Mam nadzieję, że lepiej tłumaczy ludzi pochodzących z oops background

Powiązane problemy