说实话,抽象工厂是我在规划课程之初,想砍掉的一节。不可否认它在强类型语言中非常有用,比如在Java和C++中就经常使用。因为这些语言在创建对象时,需要时刻关注类型之间的解耦,以便该对象日后可以表现多态性。但JavaScript是弱类型语言,就是说自带多态,所以开发中我们不考虑这部分的解耦。

你也可以发表一下你的看法,抽象工厂模式对前端到底是不是鸡肋?
我的看法是,抽象工厂对前端来说虽然用处不大,但也要学。为什么还要学习那?给你三个理由。
理由一:永远记住你是个工程师,而不只是前端切图仔,所以不要固步自封。用已知的编程语言,扩展自己的编程思想。比如你现在工作中用的TypeScript就需要这种抽象工厂模式。在不忙的时候,多学点是绝对有好处的。
理由二:面试应急,很多公司并不是那么专业。他们的技术负责人往往是后端或者全栈,所以免不了提及设计模式抽象工厂的问题。如果这时候作为一个前端,可以把抽象工厂讲的很好,可以得到很高的评价。
理由三:通过抽象工厂加深对"开放封闭原则"的理解。这个原则在你整个职业生涯中都非常有用,所以你理解越深,对你编程越好。
废话有点多了,我们直接开始正题,讲解抽象工厂模式。
可能你对开放封闭原则不太熟悉,所以我作一些介绍,如果你已经熟知,请看下一部分文章。
开放封闭原则是面向对象编程中的一个重要原则,它的基本思想是一个类只应该对外暴露它所需要的接口,而不应该暴露其内部的实现细节。
这个原则的目的是为了让类的实现细节保持私有,避免其他代码对类的内部实现进行修改。这样可以增强类的可重用性和可维护性,并且使得代码更加易于理解和调试。
在实际的编程中,开放封闭原则可以帮助我们避免一些常见的问题,如:内存泄漏、数据不一致、类型转换错误等。它也可以使得代码更加灵活和可扩展,可以方便地进行修改和升级。
简单工厂模式从字面就可以看出,它只适合简单的业务逻辑。我们看上节课最后简单工厂的代码,可以看到如果职位很多,这个工厂函数也会无限扩大,变成屎山。
还是拿我自己举例子,生意越做越好,野心也越来越大。这时候想称霸当地的所有娱乐行业。不光想开按摩店、洗浴、还想开KTV。这时候我们的人员管理系统的编写就需要更抽象。 我们看什么是变的?什么是不变的?开这些场所都需要门面房,再加上服务人员,这些是不变的。而变的是,什么样的门面房?什么样的服务人员?我也是小白没经验,所以先写个抽象类。
class ETFactory {
//提供场地/门市房接口
createStore() {
throw new Error("抽象方法,不允许直接调用,需重写。");
}
// 提供服务人员的接口
createUser() {
throw new Error("抽象方法,不允许直接调用,需重写。");
}
} 上面的类,只是个约定规则的类,约定了开娱乐场所的两大必要条件,地点和服务人员。这时候你说想new一个的实例,调用里边的两个方法,就会报错抛出异常(当然异常是我们自己写的)。这时候这个类就是代码最顶端的抽象了,也就是抽象工厂。
抽象工厂就像大老板一样,它不干活,只享受,想动起来,还是要有具体的实践类。比如现在我们要开个按摩店,就需要写一个具体的工厂 来干活。
// 具体工厂类(实现)继承抽象工程
class AchieveFactory extends ETFactory {
createStore() {
//提供(返回)一个门市(地址),万达的门市
return new WanDaStore();
}
createUser() {
//返回对应的技师,SPA技师
return new SPATechnician();
}
} 上面的代码我们提供了开按摩店的地点和对应的服务技师。像上面这样用来new出具体对象的类,我们一般叫做具体实现类。在工作中有抽象类,就会有具体实现类,他们都是对应出现的。
按照上面的逻辑,我们可以把门市和技师都用抽象工厂的模式去实现。先来实现门市的实体类。
class Store {
// 门市的共性方法,这里提取了都有地址的方法
getAddress(){
throw new Error('抽象方法,需要重写!')
}
}
// 万达的具体实现类
class WanDaStore extends Store{
getAddress(){
console.log('万达商场一楼金街88号')
}
}
// 万象城具体实现类
class WanXiangStore extends Store{
getAddress(){
console.log('万象城商场二楼715号')
}
} 同样我们可以按照上面的方法,把技师类也抽象和具体实现出来。
// 技师的抽象类
class Technician {
// 技师的共性方法,这里提取了技师的技能
getSkill() {
throw new Error("抽象方法,需要重写!");
}
}
// SPA技师的具体实现类
class SPATechnician{
getSkill() {
console.log('精油SPA、恋奶推背、香薰SPA')
}
}
// 柔式技师的具体实现类
class SoftTechnician{
getSkill() {
console.log('柔式按摩、躺式采耳、瑜伽按摩')
}
} 上面的代码写完,我们开一家红浪漫按摩店就可以用代码这样来编写:
// 我的红浪漫
const myHongLangMan = new AchieveFactory();
// 让它拥有门店
const myStore = myHongLangMan.createStore();
// 让它拥有员工
const technician = myHongLangMan.createUser();
// 得到门店地址,控制台输出--万达商场一楼金街88号
myStore.getAddress();
// 得到员工技能,控制台输出--精油SPA、恋奶推背、香薰SPA
technician.getSkill(); 好了,现在你需要注意了。这时候有一天我不想干SPA按摩店了,而是开一个柔式按摩。这时候的代码是不需要对抽象工厂ETFactory做任何修改的,只需要扩展它实现类就可以了。
// 再实现个类
class newAchieveFactory extends ETFactory {
createStore() {
//提供(返回)一个门市(地址)
return new WanXiangStore();
}
createUser() {
//返回对应的技师
return new SoftTechnician();
}
} 这么编写代码的好处是对原有系统不会造成潜在影响,也就是所谓的“对扩展开房,对修改封闭”,是不是在抽象工厂面前非常好实现。
(如果你在学习中有任何问题、想法和疑问,或者只是单纯的想和胖哥聊聊天,都可以加我的微信,欢迎你加我,和我一起交流。微信号:php100)
好了,这就是本期教程的全部内容了,内容对初学者可能不太好理解。希望你多看代码或者多看几遍视频。我是技术胖,希望我的视频对你有所帮助,也希望你能一键三连,因为这是我创作的最大动力了。我们下期视频见了。