设计模式之构造器模式&工厂模式

前言

设计模式一直是学习的一道坎,出这个专题一方面想提升自己,另一方面还是想帮助跟我一样的前端小白更好理解这部分的知识。今天先介绍比较常见的构造器模式和工厂模式,文章还是结合场景来展开,就不干巴巴讲概念,毕竟也没书上讲的好(菜鸡去世)。

开篇

当然,还是要先介绍什么是设计模式。

"诶,你这不是不讲概念嘛。"

"确实,但这不跟相亲一样嘛,上来就说家里俩套房不合适吧。"

首先来说, 设计模式是一种思想,它是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

设计模式的基本原则

单一功能原则

  • 如果一段代码块(函数 类 模块)负责多个功能,那么当 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())

牛阿酱:可以可以,红包也安排啦

总结

简单理解:

简单工厂模式:一个工厂生产多种产品

工厂方法:一个具体的工厂生产一个具体的产品

抽象工厂:一个具体的工厂生产一系列相关的产品

结语

新年将至,祝愿阖家幸福

#高频知识点汇总##学习路径#
全部评论
写的很好,可惜我写JAVA
1 回复 分享
发布于 2021-12-21 10:53
🎉恭喜牛友成功参与 【创作激励计划】高频知识点汇总专场,并通过审核! ------------------- 创作激励计划5大主题专场等你来写,最高可领取500元京东卡和500元实物奖品! 👉快来参加吧:https://www.nowcoder.com/discuss/804743
点赞 回复 分享
发布于 2021-12-21 16:08
写的很好,可惜我写C的
点赞 回复 分享
发布于 2021-12-21 09:04

相关推荐

04-24 10:19
华为_HR
🔍 误区纠正现场:  传言1:”OD就是低配版华为,随时会被优化“  OD全称可是”华为Offshore Development“,和华为研发体系共用同一套技术栈、项目管理流程,甚至很多重点项目的攻坚组都是OD和正式员工混编作战。去年有位同学参与鸿蒙生态开发后,带着项目经历跳槽直接拿下大厂P7,这"低配"怕是有点凡尔赛?  传言2:”转正通道形同虚设,HR的嘴骗人的鬼“   OD员工中37%通过内部考核转华为正式编(悄悄说:有个00后卷王半年解锁该成就)。转正标准透明到能当镜子照:①通过可信专业级认证 ②年度绩效B+以上 ③通过三场技术答辩——难吗?但绝对有迹可循。  传言3:”福利待遇差几个level,过节礼盒都没份“   工卡刷食堂同价、年度体检同一家机构、夜宵券照样领,区别可能只有礼盒外包装多了个OD标识(但内容物绝对没缩水!)。至于16薪+项目奖+一线城市人才补贴的组合拳。🎁 被低估的隐藏资源:  “华为权限”:从任总讲话原声课程到AI算法大牛直播,内部学习平台日均点击量比B站还高    “技术大佬直通车”:新员工能直接预约20年经验Fellow级架构师做职业规划咨询  “简历镀金效应”:接触过20+离职OD同事,履历上带"H项目攻坚""亿级用户产品迭代"的,面试邀约率平均提升60%  OD当然不是完美选择,但绝对是肉眼可见的跳板——在这里,你能用2年时间接触到别人5年都碰不到的复杂场景,能和行业TOP10%的聪明人组队打怪。  “后记”:  Q:学历/履历有短板还能尝试吗?  A:OD的简历初筛比华为社招宽松1.5个Level(举个栗子:正式岗卡死的985/211,OD可放宽至优质一本+项目经历匹配)  有需要的宝子可以斯我!!!!
华为成长空间 583人发布 投递华为等公司8个岗位
点赞 评论 收藏
分享
拼多多 暑期实习 二面,总共用时1h 左右, 被面试官疯狂拷打, 估计凉凉。首先介绍项目, 对方完全不感兴趣: 你做的这些和后端开发有什么关系?我简单介绍了下后端相关的,面试官可能觉得太简单了,没有继续问。然后就是痛苦的手撕拷打,持续50mins 左右。问题1: 给你两个班级, 每个班级共有 k 个人,你是班主任,要从每个班级中挑出1个人,使得他们的身高差最小。回答: 先排序, 然后遍历A班级,二分查找B班级中的第一个大于等于(lower_bound)A班级里的那个 的位置,然后比较那个位置和前一个位置。面试官和我不太同频,问我为什么要找第一个大于等于?二分查找不就是找一个位置吗? 面试官笑眯眯的问我是第一次接触二分搜索吗?然后计算时间复杂度。感觉完全不同频。问还有更优解法吗?回答双指针,还是固定遍历A, 然后另一个指针从B开始找比A大的,然后在和前一个也比较,取最小的。这样就是O(n).面试官提示一下,不要局限在当前这个和前一个比较,换种思路。 然后我一直在思考,对方问我双指针要怎么初始化?  因为我还没想好,就没回答。面试官: 双指针要怎么初始化?这你都不懂吗。。。? 怎么不回答我。我说新思路还没想好,面试官表示刚才那种思路的双指针要怎么初始化? 答:都初始化在第一个位置。问题2: 两个班级, 换成 N 个班级, 每个班级选1个人, 要求算出来的人里的 max - min 最小。答没思路, 面试官提示下多个指针? 考虑下指针应该如何移动。我想了想,移动最小的那个指针,直到所有指针都走到末尾,每次移动,从这个N个人里面取最大的,最小的,比较。然后算时间复杂度:n个班,每个班k个人,  我想整体的数据规模是 N = n*k , 然后我用 N 去后续表示。面试官:你为什要定义新的符号N? 算完时间复杂度,问我“从这个N个人里面取最大的,最小的”这部分可以优化吗? 我回答可以使用 map (cpp里的),面试官表示你直接说数据结构,不要说语言中的名字。问这个的时间复杂度,答logn面试官:那你开始写吧。写了大概 3 分钟。 他看了眼。问题3: ping 100ms  , curl http://1.2.3.4:8080/hello  需要多少时间?这里我考虑了4次挥手, 面试官:需要考虑这个吗?答 200ms. 问题4: 直播间,打赏金额最高的100个用户? 你应该如何实现维护?我回答使用 redis 的 zset ,  可以高效的获取top 100.面试官问:这样有什么问题吗? 如果用户特别多的情况。我想了一会,也没想出什么问题,回答没什么思路。面试官:用户太多了会有 大 key 问题, zset 删除的时候会阻塞几秒。 (我不太理解)面试官:你应该考虑怎么优化?答: string 配合 zset 使用, string kv 中存 user, money,  而 zset 中只维护 top 100 的。同时更新这俩。最后, 反问部门业务:拼多多直播带货。技术栈: 面试官看我的简历里面,cpp 太底层了我们这边不用,golang 也不用,主要是 java , 然后 redis, mysql, kafka这些。面试官问我懂不懂二分, 我当时多少有点生气💢, 不过总的来说面试官人还不错,还算友善,给了很多引导。
查看13道真题和解析 牛客创作赏金赛
点赞 评论 收藏
分享
评论
13
16
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务