工厂模式:
什么叫工厂模式,工厂就是大家大脑里想的那样,一个流水线作业的一个东西,只需要满足刚需就可以了,一个人,只干一件事,最后串起来,就是一个事件。
首先需要说一下工厂模式。工厂模式根据抽象程度的不同分为三种:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
简单工厂:
简单工厂说白了,就是需要想到你要干什么,要分几步做,把每个事件全都摆出来,完咯,开始着手建厂,在厂里把你想干的事情,全都分列清除,把条件弄好,好知道来需求的时候,知道哪些人干活。最后就是客户提的需求了,根据需求去办事。
代码案例:
/** * 宝马 */ var Baoma = function () { this.play = function () { console.log('我在造宝马'); } } /** * 奥迪 */ var Aodi = function () { this.play = function () { console.log('我在造奥迪'); } } //造宝马事件 var baoma = new Baoma(); // 运行造宝马事件 baoma.play(); // 造奥迪事件 var aodi = new Aodi(); // 运行造奥迪事件 aodi.play(); /** * 造小汽车工厂 */ var Ball = function(name) { switch (name) { case '宝马': return new Baoma(); break; case '奥迪': return new Aodi(); break; } } // 客户需求要宝马 var baoma = Ball('宝马'); // 来开造 baoma.play(); // 客户需要奥迪 var aodi = Ball('奥迪'); //来开造 aodi.play();
工厂方法:
工厂方法说白了就是在工厂里面去写方法,在外部写一个公用的方法去调取工厂的独有方法,来实现客户的需求
代码如下:
// 安全模式创建工厂类 var Ball = function (type,name) { // 判断实例是否属于ball if(this instanceof Ball) { var s = new this[type](name); console.log(s) return s; }else { return; } } // 工厂原型中设置创建所有类型数据对象的基类 Ball.prototype = { baoma: function(name) { this.play = function() { console.log('我在生产'+name); } }, aodi: function(name) { this.play = function() { console.log('我在建造'+name); } }, } // 客户需求 var baoma = new Ball('baoma','宝马'); // 开始建造 baoma.play(); // 客户需求 var aodi = new Ball('aodi','奥迪'); // 开始建造 aodi.play(); /* baoma {play: ƒ} 我在建造宝马 aodi {play: ƒ} 我在生产奥迪 */
对比简单模式和方法模式,方法模式的代码,要比简单工厂模式的代码要少的多,最后只需要在工厂里面去添加方法,去调用就行了,不要再往开发零件区去填写内容了。
抽象工厂:
抽象工厂,说白了比较抽象的,说是抽象,其实看着也差不多应改,在开始的时候建一个工厂,里面去判断这个方法,有这个方法的时候就开始继承,指向,继承,最后运行事件,感觉代码老多了,不易理解,要建一个私有类,完咯在工厂中找到这个类,取到类的值,用值去跑建造方法。最后当然就是需求的提交,和程序的运行了
// # 抽象工厂模式 var Sport = function(subType, superType) { if( typeof Sport[superType] === 'function'){ // 缓存类 function F() {}; // 继承父类属性和方法 F.prototype = new Sport[superType](); // 将子类constructor 指向子类 subType.constructor = subType; // 子类原型继承 “父类” subType.prototype = new F(); }else { // 不存在抽象类则抛出错误 throw new Error('未创建该抽象类'); } } // 宝马抽象类 Sport.baoma = function () { this.type = 'baoma'; } Sport.baoma.prototype = { play: function () { return new Error('抽象方法不能调用'); } } // 奥迪抽象类 Sport.aodi = function () { this.type = 'aodi'; } Sport.aodi.prototype = { play: function () { return new Error('抽象方法不能调用'); } } // 大众抽象类 Sport.dazhong = function () { this.type = 'dazhong'; } Sport.dazhong.prototype = { play: function () { return new Error('抽象方法不能调用'); } } // 宝马类 var BasketBall = function (name) { this.name = name; }; // 抽象工厂实现对宝马的继承 Sport(BasketBall,'baoma'); BasketBall.prototype.play = function () { console.log('我在造'+this.name); } // 奥迪类 var WeightLifting = function (name) { this.name = name; }; // 抽象工厂实现对奥迪的继承 Sport(WeightLifting,'aodi'); WeightLifting.prototype.play = function () { console.log('我在造'+this.name); } // 大众类 var Running = function (name) { this.name = name; }; // 抽象工厂实现对大众的继承 Sport(Running,'dazhong'); Running.prototype.play = function () { console.log('我在造'+this.name); } // 抽象工厂模式实现 var basketBall = new BasketBall('宝马'); console.log(basketBall.type);//baoma basketBall.play(); var weightLifting = new WeightLifting('奥迪'); console.log(weightLifting.type);//aodi weightLifting.play(); var running = new Running('大众'); console.log(running.type);//ball running.play(); /** 输出结果 * baoma * 我在造宝马 * aodi * 我在造奥迪 * dazhong * 我在造大众 */
在vue项目中使用,大家熟悉的莫过于路由了,其实路由页面的代码就应该算是一个简单工厂,但没有那些复杂的方法,
import Vue from 'vue' import Router from 'vue-router' import MainTab from '@/views/MainTab' import PersonRegister from '@/views/PersonRegister' Vue.use(Router) export default new Router({ routes: [ { // 根目录 path: '/', component: MainTab, redirect:'/PersonRegister', children: [ { // 人员登记 path: '/PersonRegister', name: 'PersonRegister', component: PersonRegister }, { // 签到表详情 path: '/InterviewSigin', name: 'InterviewSigin', component: () => import('@/views/InterviewSigin') }, { // 邀约人页面 path: '/inviteApproval', name: 'inviteApproval', component: () => import('@/views/inviteApproval') }, { // 删除统计 path: '/DeleteCount', name: 'DeleteCount', component: () => import('@/views/DeleteCount') }, { // 离场统计 path: '/DepartureCount', name: 'DepartureCount', component: () => import('@/views/DepartureCount') }, { // 签到表 path: '/SiginManage', name: 'SiginManage', component: () => import('@/views/SiginManage') } ] } ] })
在上面的代码中就可以看出来,他的子路由就是一块一块的,就好比是工厂模式的上面的每一方法一样,我也不知道这样嵌套这说对不对,我感觉差不多吧,你想添加页面的话,只需要在里面写一个子路由就行了。
抽象工厂模式的优点:
-
当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
-
增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
抽象工厂模式的缺点:
-
开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。
-
增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。
抽象工厂模式的适用情况:
在以下情况下可以使用抽象工厂模式:
-
一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
-
系统中有多于一个的产品族,而每次只使用其中某一产品族。
属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。 -
系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
抽象工厂模式总结
-
抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。
-
抽象工厂模式适用情况包括:一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节;系统中有多于一个的产品族,而每次只使用其中某一产品族;属于同一个产品族的产品将在一起使用;系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。