抽象工厂模式(Abstract Factory)
抽象工厂模式: 是通过对类的工厂抽象使业务用于对产品类簇的创建,而不负责创建某一类产品的实例
5.1 模范带头————抽象类
那么在javascript 中如何创建一个类呢?抽象类有什么用?与抽象类相关的都有哪些模式呢?
你知道javascript 中 abstract 还是一个保留字,所以目前来说还不能像传统面向对象语言那样轻松地创建。抽象类是一种声明但不能使用的类,当你使用就会报错。不过javascript 是灵活的,所以我们可以在类的方法中手动地抛出错误来模拟抽象类。
// 汽车抽象类,当使用其实例对象的方法时会抛出错误
var Car = function(){};
Car.prototype = {
getPrice : function(){
return new Error('抽象方法不能调用');
},
getSspeed : function(){
return new Error('抽象方法不能调用');
}
};
5.2 幽灵工厂————抽象工厂模式
// 抽象工厂方法
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 {
// 不存在该抽象类抛出的错误
throw 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 = type;
};
VehicleFactory.Bus.prototype = {
getPrice : function(){
return new Error('抽象的方法不能调用');
},
getPaggerNum : function(){
return new Error('抽象的方法不能调用');
}
}
// 货车抽象类
VehicleFactory.Truck = function(){
this.type = 'truck';
};
VehicleFactory.Truck.prototype = {
getPrice : function(){
return new Error('抽象方法不能调用');
},
getTrainLoad : function(){
return new Error('抽象方法不能调用');
}
}
<b> 你可以看到,抽象工厂类其实是一个实现子类继承父类的方法,在这个方法中,我们需要通过传递子类以及要继承父类(抽象类的名称) 并且在抽象工厂方法中又增加了一次对抽象类存在性的一次判断,如果存在,则将子类继承父类的方法。然后子类通过寄生式继承。继承父类 的原型,而是通过 new 关键字复制父类的方法。然后子类通过寄生式继承。继承父类过程中有一个地方需要注意,就是对过渡类的原型继承时, 我们不是继承父类的原型方法,还要继承父类的对象属性,所以通过 new 关键字将父类的构造函数执行一遍来复制构造函数中的属性和方法。 对抽象工厂添加抽象类也很特殊,因为抽象工厂是个方法不需要实例化对象,故只需要一份,因此直接为抽象工厂添加类的属性即可,于是我们就 可以通过点语法在抽象工厂上添加我们一会儿需要的三个汽车簇抽象类 Car, Bus, Truck.
5.3 抽象与实现
这个该如何使用呢?
听我给你讲一下,既然抽象工厂是用创建子类的(而本例中其实是让子类继承父类,是对子类的一个拓展)我们需要一些产品子类,然后让子类继承相应的产品簇抽象类
// 宝马汽车子类
var BMW = function(price, speed) {
this.price = price;
this.spped = speed;
}
// 抽象工厂实现对Car 抽象类的继承
VehicleFactory(BMW, 'Car');
BMW.prototype.getPrice = function(){
return this.price;
}
BMW.prototype.getSpeed = function(){
return this.spped;
}
// 兰博基尼汽车子类
var Lamborghini = function(price, speed){
this.price = price;
this.speed = speed;
}
// 抽象工厂实现对Car 抽象类的继承
VehicleFactory(Lamborghini, 'Car');
Lamborghini.prototype.getPrice = function(){
return this.price;
}
Lamborghini.prototype.getSpeed = function(){
return this.speed;
}
// 宇通汽车子类
var YUTONG = function(price, passenger) {
this.price = price;
this.passenger = passenger;
}
// 抽象工厂实现对 Bus 抽象类的继承
VehicleFactory(YUTONG, 'Bus');
YUTONG.prototype.getPrice = function() {
return this.price;
}
YUTONG.prototype.getPaggerNum = function() {
return this.passenger;
}
// 奔驰汽车子类
var BenzTruck = function(price, trainLoad) {
this.price = price;
this.trainLoad = trainLoad;
}
// 抽象工厂实现对 Truck 抽象类的继承
VehicleFactory(BenzTruck, 'Truck')
BenzTruck.prototype.getPrice = function() {
return this.price;
}
BenzTruck.prototype.getTrainLoad = function() {
return this.price;
}
通过抽象工厂, 我们就能知道每个子类到底是哪一类别了,然后他也具有了该类所必备的属性和方法了。
单例测试一下
var truck = new BenzTruck(100000, 1000);
console.log(truck.getPrice()); // 100000
console.log(truck.type); // truck
收获
抽象工厂模式是设计模式中最为抽象的一种,也是创建中唯一一种抽象化创建模式。该模式创建出的结果不是一个真实的对象实例,而是一个类簇,它制定了类的结构,这也就区别于简单工厂模式创建单一对象,工厂方法模式创建多类对象。当然由于Javascript中不支持抽象化创建于虚拟方法,所以导致这种模式不能向其他面向对象语言中应用的那么广泛。