使用场景

  1. 为了解决多个类似对象声明的问题,我们可以使用一种叫做 工厂模式的方法,这种方法 就是为了解决实例化对象产生大量重复的问题。

大致区分类型

简单工厂

  • 简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。
  • 不修改代码的话,是无法扩展的。

    工厂方法模式

  • 工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。

  • 在同一等级结构中,支持增加任意产品。

    抽象工厂

  • 抽象工厂是应对产品族概念的。比如说,每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法。

  • 应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品。

简单工厂模式

简单工厂模式其实并不算是一种设计模式,更多的时候是一种编程习惯。

定义

定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。

demo

User就是一个简单工厂,在该函数中有3个实例中分别对应不同的权限的用户。当我们调用工厂函数时,只需要传递superAdmin, admin, user这三个可选参数中的一个获取对应的实例对象。

  1. //User类
  2. class User {
  3. //构造器
  4. constructor(opt) {
  5. this.name = opt.name;
  6. this.viewPage = opt.viewPage;
  7. }
  8. //静态方法
  9. static getInstance(role) {
  10. switch (role) {
  11. case 'superAdmin':
  12. return new User({ name: '超级管理员', viewPage: ['首页', '通讯录', '发现页', '应用数据', '权限管理'] });
  13. break;
  14. case 'admin':
  15. return new User({ name: '管理员', viewPage: ['首页', '通讯录', '发现页', '应用数据'] });
  16. break;
  17. case 'user':
  18. return new User({ name: '普通用户', viewPage: ['首页', '通讯录', '发现页'] });
  19. break;
  20. default:
  21. throw new Error('参数错误, 可选参数:superAdmin、admin、user')
  22. }
  23. }
  24. }
  25. //调用
  26. let superAdmin = User.getInstance('superAdmin');
  27. let admin = User.getInstance('admin');
  28. let normalUser = User.getInstance('user');

工厂方法模式

工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。

demo

  1. class User {
  2. constructor(name = '', viewPage = []) {
  3. if(new.target === User) {
  4. throw new Error('抽象类不能实例化!');
  5. }
  6. this.name = name;
  7. this.viewPage = viewPage;
  8. }
  9. }
  10. class UserFactory extends User {
  11. constructor(name, viewPage) {
  12. super(name, viewPage)
  13. }
  14. create(role) {
  15. switch (role) {
  16. case 'superAdmin':
  17. return new UserFactory( '超级管理员', ['首页', '通讯录', '发现页', '应用数据', '权限管理'] );
  18. break;
  19. case 'admin':
  20. return new UserFactory( '普通用户', ['首页', '通讯录', '发现页'] );
  21. break;
  22. case 'user':
  23. return new UserFactory( '普通用户', ['首页', '通讯录', '发现页'] );
  24. break;
  25. default:
  26. throw new Error('参数错误, 可选参数:superAdmin、admin、user')
  27. }
  28. }
  29. }

抽象工厂模式

  1. **抽象工厂模式并不直接生成实例, 而是用于对产品类簇的创建**

demo

  1. /**
  2. * 实现 subType类对工厂类中的superType类型的抽象类的继承
  3. * @param subType 要继承的类
  4. * @param superType 工厂类中的抽象类type
  5. */
  6. const VehicleFactory = function(subType, superType) {
  7. if (typeof VehicleFactory[superType] === 'function') {
  8. function F() {
  9. this.type = '车辆'
  10. }
  11. F.prototype = new VehicleFactory[superType]()
  12. subType.constructor = subType
  13. subType.prototype = new F()
  14. // 因为子类subType不仅需要继承superType对应的类的原型方法,还要继承其对象属性
  15. } else throw new Error('不存在该抽象类')
  16. }
  17. VehicleFactory.Car = function() {
  18. this.type = 'car'
  19. }
  20. VehicleFactory.Car.prototype = {
  21. getPrice: function() {
  22. return new Error('抽象方法不可使用')
  23. },
  24. getSpeed: function() {
  25. return new Error('抽象方法不可使用')
  26. }
  27. }
  28. const BMW = function(price, speed) {
  29. this.price = price
  30. this.speed = speed
  31. }
  32. VehicleFactory(BMW, 'Car') // 继承Car抽象类
  33. BMW.prototype.getPrice = function() { // 覆写getPrice方法
  34. console.log(`BWM price is ${this.price}`)
  35. }
  36. BMW.prototype.getSpeed = function() {
  37. console.log(`BWM speed is ${this.speed}`)
  38. }
  39. const baomai5 = new BMW(30, 99)
  40. baomai5.getPrice() // BWM price is 30
  41. baomai5 instanceof VehicleFactory.Car // true