设计模式之构造器模式&工厂模式
前言
设计模式一直是学习的一道坎,出这个专题一方面想提升自己,另一方面还是想帮助跟我一样的前端小白更好理解这部分的知识。今天先介绍比较常见的构造器模式和工厂模式,文章还是结合场景来展开,就不干巴巴讲概念,毕竟也没书上讲的好(菜鸡去世)。
开篇
当然,还是要先介绍什么是设计模式。
"诶,你这不是不讲概念嘛。"
"确实,但这不跟相亲一样嘛,上来就说家里俩套房不合适吧。"
首先来说, 设计模式是一种思想,它是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式的基本原则
单一功能原则
- 如果一段代码块(函数 类 模块)负责多个功能,那么当 A 功能需求发生改变的时候改动了代码,就有可能导致 B 功能出现问题,所以一段代码块只应该负责一个职责。
开放封闭原则
- 通过修改老代码来实现新功能可能导致老模块出现 BUG,所以我们应该通过开发新代码块来实现新功能。
里式替换原则
- 程序中的子类应该可以替换父类出现的任何地方并保持预期不变。所以子类尽量不要改变父类方法的预期行为。
接口隔离原则
- 当类 A 只需要接口 B 中的部分方法时,因为实现接口需要实现其所有的方法,于是就造成了类 A 多出了部分不需要的代码。这时应该将 B 接口拆分,将类A需要和不需要的方法隔离开来。
依赖反转原则
- 抽象不应该依赖细节,细节应该依赖于抽象。核心是面向接口编程,我们应该依赖于抽象接口,而不是具体的接口实现类或具体的对象。
正文
构造器模式
话说牛村前些年出了一个大学生,叫牛二柱。作为村里唯一的大学生,二柱学习刻苦,每天基本两点一线,却忽略了个人感情生活,二柱倒无所谓,这不还有几天就要新年了,父母催二柱赶紧找对象,二柱抵不住父母软磨硬泡,答应父母回家一定带个对象回家。一天晚上回宿舍晚上,看到路上散落几本书,二柱拾起一本名为《JavaScript设计模式》的书,突然灵光一现,拍了怕书,“这不就有对象了嘛”。回去后,二柱写下几行代码
const myOnly = { name: '牛二花', age: 20, character: '温柔贤惠', hobby: '唱歌跳舞' }
一个温柔贤惠的牛二花就出现在二柱眼前,二柱高兴地带着二花回了家,父母看了很是满意,不久牛二柱这个能力被好朋友牛铁牛知道了,铁牛找了二柱,希望也能帮自己找对象,二柱毫不犹豫地答应,打开电脑又写下这段代码
const TieNiuOnly = { name: '牛翠花', age: 18, character: '活泼', hobby: '弹琴' }
自从二柱帮铁牛找着对象后,这找他帮忙的可是越来越多,这一看从家门口排到村口
二柱心想,完了完了,这得写到啥时候。于是,掏出那本在路上拾到的书。诶,有了,可以用构造器的模式嘛,于是二柱修改了一下代码
//构造器——当新建对象的内存被分配后,用来初始化该对象的特殊函数 function createYourOnly(name,age,character,hobby) { this.name = name this.age = age this.character = character this.hobby = hobby } //对象说明(函数放在原型上,单一实例就能在每一个创建createYourOnly对象之间共享) createYourOnly.prototype.instruction = function () { console.log(`My name is ${this.name}`) }
于是乎,二柱不用再一个一个手写字面量,需要找对象的,只需要调用一次构造器就可以了
const TutuOnly = new createYourOnly('牛阿兰',23,'开朗聪明','爬山、唱K') const NiuYeYeOnly = new createYourOnly('牛阿华',20,'机灵懂事','吃饭睡觉')
在面向对象编程中,构造器是一个当新建对象的内存被分配后,用来初始化该对象的一个特殊函数。在 JavaScript 中一切皆对象。
对象构造器是被用来创建特殊类型的对象的,首先它要准备使用的对象,其次在对象初次被创建时,通过接收参数,构造器要用来对成员的属性和方法进行赋值。
工厂模式
简单工厂模式
自从二柱帮村里解决大部分人的单身问题之后,二柱的名气可谓越发红火。一天,牛大娃和牛二娃来找二柱。
“二柱呀,上次给我俩找的对象只知道一点信息,能给我找一个吃辣的四川妹子不 ~ ”
等牛大娃说完,二娃在旁边说
“我也要,我想找个广州的,我喜欢那种口味清淡一点的女生”
二柱:我丢,这俩货要求还有点多
没办法了,谁叫二柱热心肠呢,也就多个城市,也不难
function createSiChuanOnly(name,age,character,hobby) { this.name = name this.age = age this.character = character this.hobby = hobby this.city = '四川' this.eathobby = '辣的' }
function createGuangZhouOnly(name,age,character,hobby) { this.name = name this.age = age this.character = character this.hobby = hobby this.city = '广州' this.eathobby = '清淡' }
村里人听说对象的还能选不同城市的,急忙过去,这会二柱苦恼了,这么多城市得写到猴年马月呀。算了,选择工厂模式吧。
function createYourOnly(name, age, character, hobby, city, eathobby) { this.name = name; this.age = age; this.character = character; this.hobby = hobby; this.city = city; this.eathobby = eathobby } //主要是根据城市,然后给予对象饮食特性 function OnlycreateFactory(name, age, character, hobby, city) { let eathobby = '' switch (city) { case '四川': eathobby = '辣的' break; case '广州': eathobby = '清淡' break; ... } return new createYourOnly(name, age, character, hobby, city, eathobby); } let NiuDaWaOnly = new OnlycreateFactory('牛大妹', 20, '奔放活泼', '爬山', '四川') let NiuErWaOnly = new OnlycreateFactory('牛二妹', 20, '温柔', '羽毛球', '广州')
抽象工厂模式
话说毕业后的牛二柱去到牛村LOLO姐创办的牛爱网,帮助更多单身青年脱单。
春节临近,七大姑八大姨来八卦婚姻大事,牛爱网自然也就火热起来了。某天村里来一个叫牛阿酱的,她想要找一个东北的,一米八的高个的,长得帅的,能喝几斤白的。
牛二柱心想这咋整,哪天来个东南的,西北的,这不要了我的命
还好书里还有讲到一种工厂模式,就是抽象工厂模式
抽象工厂模式创建的是类簇,而非是具体某一个类的实例。抽象工厂模式适用于系统里有多于一个的产品族,而只需要用到某一族的类的场景
于是乎,牛二柱又进行一次修改(没办法,牛阿酱给的利是实在多)
// 抽象工厂方法 function AbstractFactoryBoy(subType, supType) { //判断抽象工厂中是否有该抽象类 if (typeof AbstractFactoryBoy[supType] === 'function') { //缓存类 function F() {} //继承父类属性和方法 F.prototype = new AbstractFactoryBoy[supType]() //将子类的constructor指向子类 subType.constructor = subType //子类原型继承父类 subType.prototype = new F() } else { throw new Error('不能创建该抽象类') } } // 北方男生抽象类 AbstractFactoryBoy.NorthBoy = function () { this.city = 'north' } AbstractFactoryBoy.NorthBoy.prototype = { north() { return new Error('抽象方法不能调用') }, myCustomization() { return new Error('抽象方法不能调用') } } //南方男生抽象类 AbstractFactoryBoy.SouthBoy = function () { this.city = 'south' } AbstractFactoryBoy.SouthBoy.prototype = { south() { return new Error('抽象方法不能调用') }, myCustomization() { return new Error('抽象方法不能调用') } } // 北方男生: 东北的男生(具体类) function NorthEastBoy(name, age, customize) { this.name = name this.age = age this.customize = customize this.city = '东北' } AbstractFactoryBoy(NorthEastBoy, 'NorthBoy') NorthEastBoy.prototype.north = function () { return `My name is ${this.name}, I’m ${this.city}汉子,My age is ${this.age}` } NorthEastBoy.prototype.myCustomization = function () { return `My Dream ${this.customize}` }
过几天,牛阿酱问二柱找对象的事
牛二柱:“再说一下你要求吧”
牛阿酱(害羞):“东北的,一米八的高个的,长得帅的,能喝几斤白的”
const JiangNorthEastBoy = new NorthEastBoy('Niu_BoyBoy', 23, {beer: '喝几斤白', character: '一米八、高且帅'}) console.log(JiangNorthEastBoy.north()) console.log(JiangNorthEastBoy.myCustomization())
牛阿酱:可以可以,红包也安排啦
总结
简单理解:
简单工厂模式:一个工厂生产多种产品
工厂方法:一个具体的工厂生产一个具体的产品
抽象工厂:一个具体的工厂生产一系列相关的产品
结语
新年将至,祝愿阖家幸福
#高频知识点汇总##学习路径#