在现实生活中,工厂是负责生产产品的,比如牛奶、面包或礼物等,这些产品满足了我们日常的生理需求。
作为一名 Web 软件开发工程师,在软件系统的设计与开发过程中,我们可以利用设计模式来提高代码的可重用性、可扩展性和可维护性。在众多设计模式当中,有一种被称为工厂模式的设计模式,它提供了创建对象的最佳方式。
工厂模式可以分为:简单工厂模式、工厂方法模式和抽象工厂模式。本文阿宝哥将详细介绍抽象工厂模式,不过在介绍该模式之前,我们先来回顾一下简单工厂模式和工厂方法模式。
简单工厂模式又叫 静态方法模式,因为工厂类中定义了一个静态方法用于创建对象。简单工厂让使用者不用知道具体的参数就可以创建出所需的 ”产品“ 类,即使用者可以直接消费产品而不需要知道产品的具体生产细节。
对于刚接触简单工厂模式的小伙伴来说,看到以上的描述可能会觉得有点抽象。因此为了让小伙伴更好地理解简单工厂模式,阿宝哥以用户买车为例,来介绍一下 BMW 工厂如何使用简单工厂模式来生产小汽车。
在上图中,阿宝哥模拟了用户购车的流程,小王和小秦分别向 BMW 工厂订购了 BMW730 和 BMW840 型号的车型,接着工厂会先判断用户选择的车型,然后按照对应的模型进行生产并在生产完成后交付给用户。接下来,我们来看一下如何使用简单工厂来描述 BMW 工厂生产指定型号车子的过程。
class BMWFactory { public static produceBMW(model: "730" | "840"): BMW { if (model === "730") { return new BMW730(); } else { return new BMW840(); } } } const bmw730 = BMWFactory.produceBMW("730"); const bmw840 = BMWFactory.produceBMW("840");
在以上代码中,我们定义一个 BMWFactory
类,该类提供了一个静态的 produceBMW()
方法,用于根据不同的模型参数来创建不同型号的车子。看完以上的代码,相信很多小伙伴会觉得很熟悉,因为在一些项目中就使用了简单工厂模式。该模式很简单,在满足以下条件下可以考虑使用简单工厂模式:
了解完简单工厂模式的应用场景,接下来我们来看一下该模式的优缺点。
在一些实际的项目中,为了避免简单工厂模式带来的问题,我们可以考虑使用工厂方法模式。
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫多态工厂(Polymorphic Factory)模式,它属于类创建型模式。
在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象, 这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
在上图中,阿宝哥模拟了用户购车的流程,小王和小秦分别向 BMW 730 和 BMW 840 工厂订购了 BMW730 和 BMW840 型号的车子,接着工厂按照对应的模型进行生产并在生产完成后交付给用户。同样,我们来看一下如何使用工厂方法来描述 BMW 工厂生产指定型号车子的过程。
interface BMWFactory { produceBMW(): BMW; } class BMW730Factory implements BMWFactory { produceBMW(): BMW { return new BMW730(); } } class BMW840Factory implements BMWFactory { produceBMW(): BMW { return new BMW840(); } } const bmw730Factory = new BMW730Factory(); const bmw840Factory = new BMW840Factory(); const bmw730 = bmw730Factory.produceBMW(); const bmw840 = bmw840Factory.produceBMW();
在以上代码中,我们分别创建了 BMW730Factory 和 BMW840Factory 两个工厂类,然后使用这两个类的实例来生产不同型号的车子。相比前面的简单工厂模式,工厂方法模式通过创建不同的工厂来生产不同的产品。下面我们来看一下工厂方法有哪些优缺点。
这里我们知道在工厂方法模式中,一个具体工厂只能创建一种具体产品。很明显这限制该模式的使用场景,那么我们是否能突破该限制呢?答案是可以的。下面我们来介绍抽象工厂模式。
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。 但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。
在上图中,阿宝哥模拟了用户购车的流程,小王向 BMW 工厂订购了 BMW730,工厂按照 730 对应的模型进行生产并在生产完成后交付给小王。而小秦向 BMW 工厂订购了 BMW840,工厂按照 840 对应的模型进行生产并在生产完成后交付给小秦。接下来,我们来看一下如何使用抽象工厂来描述上述的购车过程。
1.定义 BMW 抽象类
abstract class BMW { abstract run(): void; }
2.创建 BMW730 类(BMW 730 Model)
class BMW730 extends BMW { run(): void { console.log("BMW730 发动咯"); } }
3.创建 BMW840 类(BMW 840 Model)
class BMW840 extends BMW { run(): void { console.log("BMW840 发动咯"); } }
4.定义 BMWFactory 抽象工厂
abstract class BMWFactory { abstract produce730BMW(): BMW730; abstract produce840BMW(): BMW840; }
5.创建 ConcreteBMWFactory 类
class ConcreteBMWFactory extends BMWFactory { produce730BMW(): BMW730 { return new BMW730(); } produce840BMW(): BMW840 { return new BMW840(); } }
6.生产并发动 BMW730 和 BMW840
const bmwFactory = new ConcreteBMWFactory(); const bmw730 = bmwFactory.produce730BMW(); const bmw840 = bmwFactory.produce840BMW(); bmw730.run(); bmw840.run();
以上代码运行后的输出结果为:
[LOG]: BMW730 发动咯 [LOG]: BMW840 发动咯
通过观察以上的输出结果,我们可以知道我们的 ConcreteBMWFactory 已经可以正常工作了。在 ConcreteBMWFactory 类中,阿宝哥定义了 produce730BMW()
和 produce840BMW()
这两个方法,它们分别用于生产 BMW730 和 BMW840 车子。
看到这里相信有的小伙会有疑问 —— 抽象工厂模式与工厂方法模式有什么区别呢?
抽象工厂模式与工厂方法模式最大的区别在于:工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。 当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。
了解完抽象工厂模式与工厂方法模式的区别,最后我们来一起看一下抽象工厂模式的优缺点。
根据模式是用来完成什么工作来划分,这种方式可分为 创建型模式、结构型模式和行为型模式 3 种。本文介绍的工厂方法和抽象工厂属于创建型模式,该模式用于描述 “怎样创建对象”,它的主要特点是 “将对象的创建与使用分离”。
GoF(Gang of Four)中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。其中阿宝哥已经介绍过单例、工厂方法和抽象工厂,在后续的文章中阿宝哥将介绍建造者模式及如何基于建造者设计模式实现以下功能,感兴趣的小伙伴记得关注哟。
let builder: QueryBuilder = new QueryBuilder(); let query: Query = new Query(); builder.query = query; builder.bool().shouldMatch("lot_number", 307).bool().mustMatch("expiry_date", "September 2020"); console.log(query.toString());
1995 年,艾瑞克·伽马(ErichGamma)、理査德·海尔姆(Richard Helm)、拉尔夫·约翰森(Ralph Johnson)、约翰·威利斯迪斯(John Vlissides)等 4 位作者合作出版了《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书,在本教程中收录了 23 个设计模式,这是设计模式领域里程碑的事件,导致了软件设计模式的突破。这 4 位作者在软件开发领域里也以他们的 “四人组”(Gang of Four,GoF)匿名著称。