简单工厂
有一个函数能够创建对象,并且这个函数用的是(),而不是通过new得来的,此时这个函数就是工厂函数;
工厂模式是对象的创建模式之一,和传统new创建对象相比;工厂模式使用的是工厂函数来创建对象的。
下面的代码就是简单的工厂的创建
1 <script> 2 function createPerson(name, age, sex) { 3 return { 4 name: name, 5 age: age, 6 sex: sex, 7 sayHello: function() { 8 console.log("你好我是" + this.name + "今年" + this.age + "岁了,我是一个" + this.sex) 9 } 10 } 11 }; 12 var xiaoming = createPerson("小明", 12, '男生'); 13 var xiaohong = createPerson("小红", 13, "女生") 14 console.log(xiaoming) 15 console.log(xiaohong) 16 </script>
此时会发现一个问题,上面的工厂模式不能使用instanceof,因为对象是通过圆括号直接执行的
1 var xiaoming = new createPerson("小明", 12, '男生'); 2 var xiaohong = createPerson("小红", 13, "女生") 3 console.log(xiaoming instanceof createPerson) 4 console.log(xiaohong instanceof createPerson)
此时我们会发现都为false
我们来看下面工厂函数的基本雏形
1 <script> 2 function Car(color, doors) { 3 this.color = color; 4 this.doors = doors; 5 } 6 Car.prototype.hello = function() { 7 console.log("你好,我是小汽车,我的颜色是" + this.color + "色,一共有" + this.doors + "个门"); 8 }; 9 // 工厂类型 10 function createVihicle(color, doors) { 11 return new Car(color, doors); 12 } 13 var car1 = new createVihicle("红", 2) 14 var car2 = new createVihicle("黑", 4) 15 console.log(car1) 16 console.log(car2) 17 console.log(car1 instanceof Car) 18 console.log(car2 instanceof Car) 19 </script>
此时我们有难免有一个疑问,为什么要多次一举?不直接new Car呢?
我们说工厂模式实际上就是一种思维方式的转变,它的本质是面向接口编程。
构造函数使用的是new操作符,通过new实现的结果我们称之为“针对实现编程”
普通工厂
1 <script> 2 // 小汽车 3 function Car(color, doors) { 4 this.color = color; 5 this.doors = doors; 6 // 这个地方要return,因为工厂类里面使用的是car执行,不是new,所以不会自动return 7 return this; 8 } 9 // 大卡车 10 function Trank(weight) { 11 this.weight = weight; 12 return this; 13 } 14 // 工厂类型 15 function createVihicle(type) { 16 // 通过type进行判断,如果是Car则表示创建小汽车,如果Trank则表示创建大卡车 17 if (type == "Car") { 18 // apply的作用是执行函数的上下文 19 return Car.apply(new Car(), [].slice.call(arguments, 1)) 20 } else if (type == 'Trank') { 21 return Trank.apply(new Trank(), [].slice.call(arguments, 1)) 22 } 23 } 24 25 var xiaoqiche = new createVihicle("Car", "red", 4); 26 var dakache = new createVihicle("Trank", 500) 27 console.log(xiaoqiche) 28 console.log(dakache) 29 console.log(xiaoqiche instanceof Car) 30 console.log(dakache instanceof Trank) 31 </script>
抽象工厂
抽象工厂就是提供一个注册方法,然后实例这个类。
工厂维护一个类的清单,我们用一个对象来维持当前的所有的类内容,注册的时候可以提供预审查功能。比如我们要求所有的注册类都必须要有update和render方法,否则不允许注册
1 <script> 2 function Duck(color, age) { 3 this.color = color; 4 this.age = age; 5 return this; 6 } 7 Duck.prototype.update = function() {} 8 Duck.prototype.render = function() {} 9 function Chicken(color,age) { 10 this.color = color; 11 this.age = age; 12 return this; 13 } 14 Chicken.prototype.update = function() {}; 15 Chicken.prototype.render = function() {}; 16 // 定义一个工厂 17 var Factory = (function() { 18 // 存储的是类型,不同的角色 19 var types = {}; 20 return { 21 registFactory: function(type, typeFunction) { 22 // 预审查 23 if (!typeFunction.prototype.update || !typeFunction.prototype.render) { 24 throw new Error(type + "类型没有注册成功,请设置update和render方法后再次进行注册") 25 return; 26 } 27 // 给types对象注册方法 28 types[type] = typeFunction; 29 }, 30 // 生成演员 31 careateActor: function(type) { 32 return types[type].apply(new types[type](), [].slice.call(arguments, 1)); 33 } 34 } 35 36 })(); 37 // 注册 38 Factory.registFactory("Duck", Duck); 39 Factory.registFactory("Chicken", Chicken); 40 // 实例,必须要先注册才能进行实例 41 var yazi = Factory.careateActor("Duck", "黄", 1) 42 var xiaoji = Factory.careateActor("Chicken", "红",2) 43 console.log(yazi) 44 console.log(xiaoji) 45 </script>