工厂模式是用来构建产品的,
如果我们有 N 个工厂,将它们放在一个数组中: [factory1, factory2, ..., factoryN] ,这 N 个工厂的行为都是一样的,区别仅在于工厂内部的产品不同。
我们的目的是:最终使用时,忽略工厂的差异、产品的差异,只通过一种方式即可实现所有工厂、产品的操作;同时,工厂的类别需要易于扩展。
工厂
工厂是一个含义模糊的术语,表示可以创建一些东西(产品)的函数、方法、类。工厂存在的目的在于创建不同种类的产品。
简单工厂模式
简单工厂模式不属于设计模式。简单工厂模式的实现很简单,一般都有大量的 if-else 或 switch-case 语句
function PersonFactory(type: string) {switch(type) {case 'user': return new User();case 'admin': return new Admin();case 'custom': return new Custom();}}
工厂方法模式
工厂方法模式是一种创建型设计模式,其在父类(通常为抽象类)中定义一个创建对象的方法,然后由子类决定实例化对象的类型。
// 所有部门的父类abstract class Department {public abstract createEmployee(id: string): Employee;public fire(id: string) {let employee = this.createEmployee(id)employee.dismiss()}}// IT 部门class ITDepartment extends Department {public createEmployee(id: string): Employee {return new Programmer(id)}}// 财务部门class AccountingDepartment extends Department {public createEmployee(id: string): Employee {return new Accountant(id)}}// 所有职员的父类abstract class Employee {public id: stringpublic constructor(id: string) {this.id = id}public abstract dismiss(): void}// 职员——程序员class Programmer extends Employee {constructor(id) {super(id)}dismiss() {}}// 职员——会计员class Accountant extends Employee {constructor(id) {super(id)}dismiss() {}}
上面代码中,我们将对所有职工的解雇操作 Employee.fire() 都封装在了父类 Department 中,这样我们就可以根据部门、职工 id 实现对任何一个人的操作:
(new ITDepartment()).fire('12001') // 解雇 IT 部门里编号为 12001 的职工(new AccountingDepartment()).fire('12008') // 解雇财务部门里编号为 12008 的职工
抽象工厂方法
抽象工厂方法是一种创建型设计模式,它能创建 一系列相关的对象 。
抽象工厂定义了用于创建不同产品的接口,但实际的创建工作由具体工厂类完成。每个具体工厂类对应一个特定的产品。
客户端仅通过抽象接口与工厂和产品交互。该接口应实现同一客户端与不同产品的交互。
// 抽象工厂的接口:构建的是 ProductA 和 ProductB 这两个相关的产品// ProductA 会有很多分类如: ProductA1 ProductA2 ...// ProductB 会有很多分类如: ProductB1 ProductB2 ...// 因此需要实现不同的具体工厂类,构建相关的 ProductA 和 ProductBinterface AbstractFactory {createProductA(): AbstractProductA;createProduceB(): AbstractProductB;}// 一号工厂用于构建 ProductA1 和 ProductB1 这两个产品class FactoryA implements AbstractFactory {public createProductA(): AbstractProductA {return new ProductA1();}public createProductB: AbstractProductB {return new ProductB1();}}// 2 号工厂用于构建 ProductA2 和 ProductB2 这两个产品class FactoryB implements AbstractFactory {public createProductA: AbstractProductA {return new ProductA2();}public createProductB: AbstractProductB {return new ProductB2();}}// 定义 A 产品的接口interface AbstractProductA {usefulMethodA();}// ProductA 的一个具体产品类:Productclass ProductA1 implements AbstractProductA {public usefulMethodA() {}}// ProductA 的另一个具体产品类:ProductA2class ProductA2 implements AbstractProductA {public usefulMethodA() {}}// 定义 B 产品的接口interface AbstractProductB {usefulMethodB();anotherUsefulMethodB(collaborator: AbstractProductA); // 抽象工厂用于构建一系列 相关 的对象}// ProductB 的一个具体产品类: ProductB1class ProductB1 implements AbstractProductB {public usefulMethod() {}public anotherUsefulMethodB(collaborator: AbstractProductA) {// 这里有与 collaborator 相关的操作}}// ProductB 的另一个具体产品类: ProductB2class ProductB2 implements AbstractProductB {public usefulMethodB() {}public anotherUsefulMethodB(collaborator: AbstractProductA) {// 这里有与 collaborator 相关的操作}}
客户端代码:
function client(factory: AbstractorFactory) {// 获得相关的两个产品:ProductA ProductBconst productA = factory.createProductA();const productB = factory.createProductB();// 可以看到:不管具体产品类的组合是 ProductA1 ProductB1 还是 ProductA2 ProductB2,// 只需调用在接口 AbstractProductA 和 AbstractProductB 中声明的方法即可productA.usefulMethod();productB.anotherUsefulMethod(productA);}client(new Factory1()); // Factory1 将会创建 ProductA1 和 ProductB1 这两个相关的产品client(new Factory2()); // Factory2 将会创建 ProductA2 和 ProductB2 这两个相关的产品
若将来还需要增添一个新的系列,如:ProductA3 和 ProductB3,或者根据现有的产品组合一个新的系列,如:ProductA1 和 ProductB2,那么我们直接仿照具体工厂类 Factory1 或 Factory2 的格式写一个新的具体工厂类即可。
若需要增添一个新的产品,如:ProductC1,那么现有的抽象工厂可能就不适合了,我们可以尝试继承接口或重构代码。
