工厂模式是用来构建产品的,

如果我们有 N 个工厂,将它们放在一个数组中: [factory1, factory2, ..., factoryN] ,这 N 个工厂的行为都是一样的,区别仅在于工厂内部的产品不同。

我们的目的是:最终使用时,忽略工厂的差异、产品的差异,只通过一种方式即可实现所有工厂、产品的操作;同时,工厂的类别需要易于扩展。

工厂

工厂是一个含义模糊的术语,表示可以创建一些东西(产品)的函数、方法、类。工厂存在的目的在于创建不同种类的产品。

简单工厂模式

简单工厂模式不属于设计模式。简单工厂模式的实现很简单,一般都有大量的 if-elseswitch-case 语句

  1. function PersonFactory(type: string) {
  2. switch(type) {
  3. case 'user': return new User();
  4. case 'admin': return new Admin();
  5. case 'custom': return new Custom();
  6. }
  7. }

工厂方法模式

工厂方法模式是一种创建型设计模式,其在父类(通常为抽象类)中定义一个创建对象的方法,然后由子类决定实例化对象的类型。

  1. // 所有部门的父类
  2. abstract class Department {
  3. public abstract createEmployee(id: string): Employee;
  4. public fire(id: string) {
  5. let employee = this.createEmployee(id)
  6. employee.dismiss()
  7. }
  8. }
  9. // IT 部门
  10. class ITDepartment extends Department {
  11. public createEmployee(id: string): Employee {
  12. return new Programmer(id)
  13. }
  14. }
  15. // 财务部门
  16. class AccountingDepartment extends Department {
  17. public createEmployee(id: string): Employee {
  18. return new Accountant(id)
  19. }
  20. }
  21. // 所有职员的父类
  22. abstract class Employee {
  23. public id: string
  24. public constructor(id: string) {
  25. this.id = id
  26. }
  27. public abstract dismiss(): void
  28. }
  29. // 职员——程序员
  30. class Programmer extends Employee {
  31. constructor(id) {super(id)}
  32. dismiss() {}
  33. }
  34. // 职员——会计员
  35. class Accountant extends Employee {
  36. constructor(id) {super(id)}
  37. dismiss() {}
  38. }

上面代码中,我们将对所有职工的解雇操作 Employee.fire() 都封装在了父类 Department 中,这样我们就可以根据部门、职工 id 实现对任何一个人的操作:

  1. (new ITDepartment()).fire('12001') // 解雇 IT 部门里编号为 12001 的职工
  2. (new AccountingDepartment()).fire('12008') // 解雇财务部门里编号为 12008 的职工

抽象工厂方法

抽象工厂方法是一种创建型设计模式,它能创建 一系列相关的对象

抽象工厂定义了用于创建不同产品的接口,但实际的创建工作由具体工厂类完成。每个具体工厂类对应一个特定的产品。

客户端仅通过抽象接口与工厂和产品交互。该接口应实现同一客户端与不同产品的交互。

  1. // 抽象工厂的接口:构建的是 ProductA 和 ProductB 这两个相关的产品
  2. // ProductA 会有很多分类如: ProductA1 ProductA2 ...
  3. // ProductB 会有很多分类如: ProductB1 ProductB2 ...
  4. // 因此需要实现不同的具体工厂类,构建相关的 ProductA 和 ProductB
  5. interface AbstractFactory {
  6. createProductA(): AbstractProductA;
  7. createProduceB(): AbstractProductB;
  8. }
  9. // 一号工厂用于构建 ProductA1 和 ProductB1 这两个产品
  10. class FactoryA implements AbstractFactory {
  11. public createProductA(): AbstractProductA {
  12. return new ProductA1();
  13. }
  14. public createProductB: AbstractProductB {
  15. return new ProductB1();
  16. }
  17. }
  18. // 2 号工厂用于构建 ProductA2 和 ProductB2 这两个产品
  19. class FactoryB implements AbstractFactory {
  20. public createProductA: AbstractProductA {
  21. return new ProductA2();
  22. }
  23. public createProductB: AbstractProductB {
  24. return new ProductB2();
  25. }
  26. }
  27. // 定义 A 产品的接口
  28. interface AbstractProductA {
  29. usefulMethodA();
  30. }
  31. // ProductA 的一个具体产品类:Product
  32. class ProductA1 implements AbstractProductA {
  33. public usefulMethodA() {
  34. }
  35. }
  36. // ProductA 的另一个具体产品类:ProductA2
  37. class ProductA2 implements AbstractProductA {
  38. public usefulMethodA() {
  39. }
  40. }
  41. // 定义 B 产品的接口
  42. interface AbstractProductB {
  43. usefulMethodB();
  44. anotherUsefulMethodB(collaborator: AbstractProductA); // 抽象工厂用于构建一系列 相关 的对象
  45. }
  46. // ProductB 的一个具体产品类: ProductB1
  47. class ProductB1 implements AbstractProductB {
  48. public usefulMethod() {
  49. }
  50. public anotherUsefulMethodB(collaborator: AbstractProductA) {
  51. // 这里有与 collaborator 相关的操作
  52. }
  53. }
  54. // ProductB 的另一个具体产品类: ProductB2
  55. class ProductB2 implements AbstractProductB {
  56. public usefulMethodB() {
  57. }
  58. public anotherUsefulMethodB(collaborator: AbstractProductA) {
  59. // 这里有与 collaborator 相关的操作
  60. }
  61. }

客户端代码:

  1. function client(factory: AbstractorFactory) {
  2. // 获得相关的两个产品:ProductA ProductB
  3. const productA = factory.createProductA();
  4. const productB = factory.createProductB();
  5. // 可以看到:不管具体产品类的组合是 ProductA1 ProductB1 还是 ProductA2 ProductB2,
  6. // 只需调用在接口 AbstractProductA 和 AbstractProductB 中声明的方法即可
  7. productA.usefulMethod();
  8. productB.anotherUsefulMethod(productA);
  9. }
  10. client(new Factory1()); // Factory1 将会创建 ProductA1 和 ProductB1 这两个相关的产品
  11. client(new Factory2()); // Factory2 将会创建 ProductA2 和 ProductB2 这两个相关的产品

若将来还需要增添一个新的系列,如:ProductA3 和 ProductB3,或者根据现有的产品组合一个新的系列,如:ProductA1 和 ProductB2,那么我们直接仿照具体工厂类 Factory1 或 Factory2 的格式写一个新的具体工厂类即可。

若需要增添一个新的产品,如:ProductC1,那么现有的抽象工厂可能就不适合了,我们可以尝试继承接口或重构代码。