Skip to content

Latest commit

 

History

History
97 lines (86 loc) · 3.53 KB

File metadata and controls

97 lines (86 loc) · 3.53 KB

三. 抽象工厂模式

通过对类的工厂抽象使其业务用于对产品类簇的创建,而不负责创建某一类产品的实例。也就是说我们要创建一个抽象类。这也是面向对象的开发语言中一种很常见的开发模式。

场景

var Car = function() {};
Car.prototype.getPrice = function() {
  return new Error('抽象方法不能调用,需自行实现');
};
Car.prototype.getSpeed = function() {
  return new Error('抽象方法不能调用,需自行实现');
};

由于 JavaScript 在没有 abstract 的具体实现,所以我们需要如上手动实现,也即是在创建这个类的时候,要求使用这些方法,我们需要手动去重写它,而不能继承使用。因为 在大型的应用中,总有一些子类去继承一些父类,这些父类经常会定义一些必要的方法,但是不会具体的去实现,会去要求子类自行实现。如果子类没有重写这些方法而去调用他,就会报错。

// 抽象工厂方法
var VehicleFactory = function(subType, superType) {
  //判断抽象工厂中是否有该抽象类
  if (typeof VehicleFactory[superType] === 'function') {
    //缓存类
    function F() {}
    //继承父类属性和方法
    F.prototype = new VehicleFactory[superType]();
    //将子类的constructor指向子类
    subType.constructor = subType;
    //子类原型继承父类
    subType.prototype = new F();
  } else {
    return new Error('未创建该抽象类');
  }
};

//小汽车抽象类
VehicleFactory.Car = function() {
  this.type = 'car';
};
VehicleFactory.Car.prototype = {
  getPrice: function() {
    return new Error('抽象方法不能调用');
  },
  getSpeed: function() {
    return new Error('抽象方法不能调用');
  }
};
//公共汽车抽象类
VehicleFactory.Bus = function() {
  this.type = 'Bus';
};
VehicleFactory.Bus.prototype = {
  getPrice: function() {
    return new Error('抽象方法不能调用');
  },
  getSpeed: function() {
    return new Error('抽象方法不能调用');
  }
};
//大卡车抽象类
VehicleFactory.Trunk = function() {
  this.type = 'Trunk';
};
VehicleFactory.Trunk.prototype = {
  getPrice: function() {
    return new Error('抽象方法不能调用');
  },
  getSpeed: function() {
    return new Error('抽象方法不能调用');
  }
};
//子类
var BMW = function(price, speed) {
  this.price = price;
  this.speed = speed;
};
VehicleFactory(BMW, 'Car');
BMW.prototype.getPrice = function() {
  return this.price;
};
BMW.prototype.getSpeed = function() {
  return this.speed;
};

//...

var three = new BMW('35w', '200');
three.getSpeed();
console.log(three.getPrice());

我们可以看出,抽象工厂其实是实现子类继承父类的方法,在这个方法里,我们需要传递子类以及需要被继承的父类的名称,并且在抽象工厂方法中,又增加了一次对抽象类存在性的一次判断,然后通过寄生式继承,在继承中我们是通过 new 关键字复制了父类的一个实例,因为我们不仅仅需要继承父类原型上的方法,还需要继承父类的属性。所以通过 new 关键字将父类的构造函数执行一遍来复制父类构造函数中的属性和方法。

通过抽象工厂,我们就能知道每一个子类到底是哪一种类别了。

同时注意,抽象类中定义的方法这是显示定义一些功能,但是没有具体的实现,而一个对象是应该具备一套完整的功能的。所以用抽象类创建的对象当然也是抽象的。所以我们还不能直接用它来创建类的实例。