接口在工厂模式中起着很重要的作用,如果不对对象进行某种类型检查的以确保其实现了必要的方法,工厂模式的好处也就所剩无几了,举个简单的例子。
Interface.js
1 // Constructor. 2 3 var Interface = function(name, methods) { 4 if(arguments.length != 2) { 5 throw new Error("Interface constructor called with " + arguments.length 6 + "arguments, but expected exactly 2."); 7 } 8 9 this.name = name;10 this.methods = [];11 for(var i = 0, len = methods.length; i < len; i++) {12 if(typeof methods[i] !== 'string') {13 throw new Error("Interface constructor expects method names to be " 14 + "passed in as a string.");15 }16 this.methods.push(methods[i]); 17 } 18 }; 19 20 // Static class method.21 22 Interface.ensureImplements = function(object) {23 if(arguments.length < 2) {24 throw new Error("Function Interface.ensureImplements called with " + 25 arguments.length + "arguments, but expected at least 2.");26 }27 28 for(var i = 1, len = arguments.length; i < len; i++) {29 var interface = arguments[i];30 if(interface.constructor !== Interface) {31 throw new Error("Function Interface.ensureImplements expects arguments " 32 + "two and above to be instances of Interface.");33 }34 35 for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {36 var method = interface.methods[j];37 if(!object[method] || typeof object[method] !== 'function') {38 throw new Error("Function Interface.ensureImplements: object " 39 + "does not implement the " + interface.name 40 + " interface. Method " + method + " was not found.");41 }42 }43 } 44 };
声明一个接口Bicycle,定义该接口应该有哪些方法
1 var Bicycle = new Interface("Bicycle",["assemble","wash","ride","repair"]);
构造一个简单的工厂BicycleShop,根据传递的模型,卖出不同类型的自行车。
1 var BicycleShop = function(){}; 2 3 BicycleShop.prototype = { 4 sellBicycle:function(model){ 5 var bicycle; 6 switch(model){ 7 case "The Speedster": 8 bicycle = new Speedster(); 9 break;10 case "The Lowrider":11 bicycle = new Lowrider();12 break;13 case "The Comfort Cruiser":14 default:15 bicycle = new ComfortCruiser();16 }17 Interface.ensureImplements(bicycle,Bicycle);18 bicycle.assemble();19 bicycle.wash();20 return bicycle;21 }22 }
建立一个Speedster类型的自行车,且该类提供了必要的方法
1 var Speedster = function(){ 2 }; 3 Speedster.prototype = { 4 assemble:function(){ 5 console.log("assemble method is exected"); 6 }, 7 wash:function(){ 8 console.log("wash method is exected"); 9 },10 ride:function(){11 console.log("ride method is exected");12 },13 repair:function(){14 console.log("repair method is exected");15 }16 }
创建一个工厂,传入模型参数
1 var californiaCruisers = new BicycleShop();2 californiaCruisers.sellBicycle("The Speedster");
结果:
然而,如果需要加入一款新车型,那么必须为此修改BicycleShop代码,哪怕这个类的实际功能并没有发生变化。因此,更好的解决办法是把SellBicycle中的方法中创建实例的这部分交给一个简单的工厂。
1 var BicycleFactory = { 2 createBicycle:function(model){ 3 var bicycle; 4 switch(model){ 5 case "The Speedster": 6 bicycle = new Speedster(); 7 break; 8 case "The Lowrider": 9 bicycle = new Lowrider();10 break;11 case "The Comfort Cruiser":12 default:13 bicycle = new ComfortCruiser();14 }15 Interface.ensureImplements(bicycle,Bicycle);16 return bicycle;17 }18 }19 20 var BicycleShop = function(){};21 22 BicycleShop.prototype = {23 sellBicycle:function(model){24 var bicycle = BicycleFactory.createBicycle(model);25 bicycle.assemble();26 bicycle.wash();27 return bicycle;28 }29 }