javascript设计模式-工厂模式(简单工厂)
接口在工厂模式中起着很重要的作用,如果不对对象进行某种类型检查的以确保其实现了必要的方法,工厂模式的好处也就所剩无几了,举个简单的例子。
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 }